Skip to content

Commit d371a52

Browse files
committed
fix(event): reject incompatible event-plugin versions below 3.0.0
Pre-3.0.0(The previous event-plugin public release is 2.2.0) event-plugin builds still link against com.alibaba.fastjson, which was removed from java-tron in #6701. When such a plugin is loaded, the NoClassDefFoundError surfaces inside the plugin's own worker thread and is swallowed by its catch(Throwable) handler. The node keeps running while silently dropping every trigger, leaving operators with no signal that the event subscription is broken. Enforce a minimum Plugin-Version at startup in EventPluginLoader.startPlugin using pf4j's VersionManager (semver). When the descriptor version is below 3.0.0, log a clear upgrade hint and return false; the existing call chain in Manager.startEventSubscribing wraps that into TronError(EVENT_SUBSCRIBE_INIT) and aborts node startup instead of silently degrading.
1 parent 0a26d23 commit d371a52

2 files changed

Lines changed: 63 additions & 0 deletions

File tree

framework/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.beust.jcommander.internal.Sets;
44
import com.fasterxml.jackson.core.JsonProcessingException;
55
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import com.google.common.base.Strings;
67
import java.io.File;
78
import java.util.HashSet;
89
import java.util.List;
@@ -14,8 +15,10 @@
1415
import org.bouncycastle.util.encoders.Hex;
1516
import org.pf4j.CompoundPluginDescriptorFinder;
1617
import org.pf4j.DefaultPluginManager;
18+
import org.pf4j.DefaultVersionManager;
1719
import org.pf4j.ManifestPluginDescriptorFinder;
1820
import org.pf4j.PluginManager;
21+
import org.pf4j.VersionManager;
1922
import org.springframework.util.StringUtils;
2023
import org.tron.common.logsfilter.nativequeue.NativeMessageQueue;
2124
import org.tron.common.logsfilter.trigger.BlockLogTrigger;
@@ -29,6 +32,16 @@
2932
@Slf4j
3033
public class EventPluginLoader {
3134

35+
/**
36+
* Minimum event-plugin Plugin-Version compatible with this node. Bumped to 3.0.0 to
37+
* reject pre-fastjson-removal builds whose worker threads would fail with
38+
* NoClassDefFoundError on com.alibaba.fastjson at runtime. The previous event-plugin
39+
* release is 2.2.0, so 3.0.0 is the first version that ships the Jackson replacement.
40+
*/
41+
static final String MIN_PLUGIN_VERSION = "3.0.0";
42+
43+
private static final VersionManager VERSION_MANAGER = new DefaultVersionManager();
44+
3245
private static EventPluginLoader instance;
3346

3447
private long MAX_PENDING_SIZE = 50000;
@@ -457,6 +470,10 @@ protected CompoundPluginDescriptorFinder createPluginDescriptorFinder() {
457470
return false;
458471
}
459472

473+
if (!isPluginVersionSupported(pluginManager, pluginId)) {
474+
return false;
475+
}
476+
460477
pluginManager.startPlugins();
461478

462479
eventListeners = pluginManager.getExtensions(IPluginEventListener.class);
@@ -471,6 +488,21 @@ protected CompoundPluginDescriptorFinder createPluginDescriptorFinder() {
471488
return true;
472489
}
473490

491+
static boolean isPluginVersionSupported(PluginManager pm, String pluginId) {
492+
String pluginVersion = pm.getPlugin(pluginId).getDescriptor().getVersion();
493+
if (Strings.isNullOrEmpty(pluginVersion)) {
494+
return false;
495+
}
496+
boolean isSupported = VERSION_MANAGER.compareVersions(pluginVersion, MIN_PLUGIN_VERSION) >= 0;
497+
498+
if (!isSupported) {
499+
logger.error(
500+
"event-plugin '{}' version {} is older than required {}, please upgrade event-plugin",
501+
pluginId, pluginVersion, MIN_PLUGIN_VERSION);
502+
}
503+
return isSupported;
504+
}
505+
474506
public void stopPlugin() {
475507
if (Objects.nonNull(pluginManager)) {
476508
pluginManager.stopPlugins();

framework/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
import static org.junit.Assert.assertEquals;
44
import static org.junit.Assert.assertFalse;
55
import static org.junit.Assert.assertTrue;
6+
import static org.mockito.Mockito.mock;
7+
import static org.mockito.Mockito.when;
68

79
import java.util.ArrayList;
810
import java.util.List;
911
import org.junit.Assert;
1012
import org.junit.Test;
13+
import org.pf4j.PluginDescriptor;
14+
import org.pf4j.PluginManager;
15+
import org.pf4j.PluginWrapper;
1116
import org.tron.common.logsfilter.trigger.BlockLogTrigger;
1217
import org.tron.common.logsfilter.trigger.TransactionLogTrigger;
1318

@@ -48,6 +53,32 @@ public void launchNativeQueue() {
4853
EventPluginLoader.getInstance().stopPlugin();
4954
}
5055

56+
@Test
57+
public void testIsPluginVersionSupported() {
58+
assertEquals("3.0.0", EventPluginLoader.MIN_PLUGIN_VERSION);
59+
// last releases before fastjson removal — must be rejected
60+
assertFalse(checkVersion("1.0.0"));
61+
assertFalse(checkVersion("2.2.0"));
62+
assertFalse(checkVersion("2.9.9"));
63+
// 3.0.0 onward — must be accepted
64+
assertTrue(checkVersion("3.0.0"));
65+
assertTrue(checkVersion("3.1.5"));
66+
assertTrue(checkVersion("10.0.0"));
67+
// empty/null version — reject
68+
assertFalse(checkVersion(""));
69+
assertFalse(checkVersion(null));
70+
}
71+
72+
private static boolean checkVersion(String version) {
73+
PluginManager pm = mock(PluginManager.class);
74+
PluginWrapper wrapper = mock(PluginWrapper.class);
75+
PluginDescriptor desc = mock(PluginDescriptor.class);
76+
when(pm.getPlugin("test")).thenReturn(wrapper);
77+
when(wrapper.getDescriptor()).thenReturn(desc);
78+
when(desc.getVersion()).thenReturn(version);
79+
return EventPluginLoader.isPluginVersionSupported(pm, "test");
80+
}
81+
5182
@Test
5283
public void testBlockLogTrigger() {
5384
BlockLogTrigger blt = new BlockLogTrigger();

0 commit comments

Comments
 (0)