Skip to content

Commit 355aca0

Browse files
authored
Adding json-rpc endpoints to plugin (#150)
1 parent e1692e8 commit 355aca0

10 files changed

Lines changed: 334 additions & 150 deletions

File tree

besu-plugin/core/src/main/java/samba/BesuSambaPlugin.java

Lines changed: 168 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33
import java.util.List;
44
import java.util.Optional;
55
import java.util.concurrent.CompletableFuture;
6+
import java.util.concurrent.ExecutionException;
67
import java.util.concurrent.atomic.AtomicBoolean;
78

89
import com.google.auto.service.AutoService;
10+
import com.sun.tools.sjavac.Log;
11+
import org.hyperledger.besu.datatypes.Hash;
12+
import org.hyperledger.besu.ethereum.core.BlockHeader;
913
import org.hyperledger.besu.plugin.BesuPlugin;
1014
import org.hyperledger.besu.plugin.ServiceManager;
1115
import org.hyperledger.besu.plugin.services.BesuConfiguration;
@@ -14,150 +18,178 @@
1418
import org.hyperledger.besu.plugin.services.PicoCLIOptions;
1519
import org.hyperledger.besu.plugin.services.RpcEndpointService;
1620
import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry;
21+
import org.hyperledger.besu.datatypes.Hash;
22+
import org.hyperledger.besu.ethereum.core.BlockBody;
23+
import org.hyperledger.besu.ethereum.core.BlockHeader;
24+
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
1725
import org.slf4j.Logger;
1826
import org.slf4j.LoggerFactory;
1927
import picocli.CommandLine;
28+
import samba.api.HistoryService;
2029
import samba.rpc.GetBlockBodyByBlockHash;
30+
import samba.rpc.GetBlockHeaderByBlockHash;
31+
import samba.rpc.GetTransactionReceiptByBlockHash;
2132

2233
@AutoService(BesuPlugin.class)
23-
public class BesuSambaPlugin implements BesuPlugin {
24-
private static final Logger LOG = LoggerFactory.getLogger(BesuSambaPlugin.class);
25-
public static final String PLUGIN_NAME = "samba";
26-
private static final String CLI_OPTIONS_PREFIX = "--plugin-" + PLUGIN_NAME + "-";
27-
28-
private ServiceManager serviceManager;
29-
private MetricCategoryRegistry metricCategoryRegistryService;
30-
private BesuConfiguration besuConfigurationService;
31-
private PicoCLIOptions picoCLIOptionsService;
32-
protected MetricsSystem metricsSystemService;
33-
private RpcEndpointService rpcEndpointService;
34-
35-
private static final AtomicBoolean registrationTaskDone = new AtomicBoolean(false);
36-
private static final AtomicBoolean startingTasksDone = new AtomicBoolean(false);
37-
38-
@CommandLine.Option(names = CLI_OPTIONS_PREFIX + "host")
39-
public String host = "0.0.0.0";
40-
41-
@CommandLine.Option(names = {"--plugin-samba-logging"})
42-
public String loggingLevel;
43-
44-
@CommandLine.Option(names = {"--plugin-samba-data-path"})
45-
public String dataPath;
46-
47-
private final CompletableFuture<SambaSDK> sambaSDKFuture = new CompletableFuture<>();
48-
49-
@Override
50-
public void register(ServiceManager serviceManager) {
51-
LOG.debug("Registering Samba plugin");
52-
this.serviceManager = serviceManager;
53-
if (registrationTaskDone.compareAndSet(false, true)) {
54-
this.metricCategoryRegistryService =
55-
this.getBesuService(this.serviceManager, MetricCategoryRegistry.class);
56-
this.besuConfigurationService =
57-
this.getBesuService(this.serviceManager, BesuConfiguration.class);
58-
this.picoCLIOptionsService = this.getBesuService(this.serviceManager, PicoCLIOptions.class);
59-
// TODO create a function
60-
this.picoCLIOptionsService.addPicoCLIOptions(PLUGIN_NAME, this);
61-
this.rpcEndpointService = this.getBesuService(this.serviceManager, RpcEndpointService.class);
62-
this.starRpcEndpoints(); // TODO use a completable future till samba is fully initialized.
34+
public class BesuSambaPlugin implements BesuPlugin, HistoryService {
35+
private static final Logger LOG = LoggerFactory.getLogger(BesuSambaPlugin.class);
36+
public static final String PLUGIN_NAME = "samba";
37+
private static final String CLI_OPTIONS_PREFIX = "--plugin-" + PLUGIN_NAME + "-";
38+
39+
private ServiceManager serviceManager;
40+
private MetricCategoryRegistry metricCategoryRegistryService;
41+
private BesuConfiguration besuConfigurationService;
42+
private PicoCLIOptions picoCLIOptionsService;
43+
protected MetricsSystem metricsSystemService;
44+
private RpcEndpointService rpcEndpointService;
45+
46+
private static final AtomicBoolean registrationTaskDone = new AtomicBoolean(false);
47+
private static final AtomicBoolean startingTasksDone = new AtomicBoolean(false);
48+
49+
@CommandLine.Option(names = CLI_OPTIONS_PREFIX + "host")
50+
public String host = "0.0.0.0";
51+
52+
@CommandLine.Option(names = {"--plugin-samba-logging"})
53+
public String loggingLevel;
54+
55+
@CommandLine.Option(names = {"--plugin-samba-data-path"})
56+
public String dataPath;
57+
58+
private final CompletableFuture<SambaSDK> sambaSDKFuture = new CompletableFuture<>();
59+
60+
@Override
61+
public void register(ServiceManager serviceManager) {
62+
LOG.debug("Registering Samba plugin");
63+
this.serviceManager = serviceManager;
64+
if (registrationTaskDone.compareAndSet(false, true)) {
65+
this.metricCategoryRegistryService =
66+
this.getBesuService(this.serviceManager, MetricCategoryRegistry.class);
67+
this.besuConfigurationService =
68+
this.getBesuService(this.serviceManager, BesuConfiguration.class);
69+
this.picoCLIOptionsService = this.getBesuService(this.serviceManager, PicoCLIOptions.class);
70+
// TODO create a function
71+
this.picoCLIOptionsService.addPicoCLIOptions(PLUGIN_NAME, this);
72+
this.rpcEndpointService = this.getBesuService(this.serviceManager, RpcEndpointService.class);
73+
this.starRpcEndpoints(); // TODO use a completable future till samba is fully initialized.
74+
}
6375
}
64-
}
65-
66-
@Override
67-
public Optional<String> getName() {
68-
return Optional.of(PLUGIN_NAME);
69-
}
70-
71-
@Override
72-
public void start() {
73-
LOG.info("Starting Samba plugin");
74-
if (startingTasksDone.compareAndSet(false, true)) {
75-
SambaSDK sdk = this.initSamba();
76-
sambaSDKFuture.complete(sdk);
77-
this.metricsSystemService = this.getBesuService(this.serviceManager, MetricsSystem.class);
76+
77+
@Override
78+
public Optional<String> getName() {
79+
return Optional.of(PLUGIN_NAME);
7880
}
79-
}
80-
81-
@Override
82-
public void stop() {
83-
LOG.info("Stopping Samba plugin");
84-
registrationTaskDone.set(false);
85-
startingTasksDone.set(false);
86-
this.besuConfigurationService = null;
87-
this.metricCategoryRegistryService = null;
88-
this.rpcEndpointService = null;
89-
this.picoCLIOptionsService = null;
90-
// TODO should we do something with Samba | its db ?
91-
// TODO call samba to stop
92-
}
93-
94-
private SambaSDK initSamba() {
95-
try {
96-
String[] options = {
97-
"--portal-subnetworks=history-network",
98-
"--p2p-advertised-ip=" + host,
99-
"--disable-json-rpc-server",
100-
"--disable-rest--server",
101-
"--logging=" + loggingLevel,
102-
"--data-path=" + dataPath
103-
};
104-
return Samba.init(options);
105-
106-
} catch (Exception e) {
107-
LOG.error("Halting Besu startup: exception in plugin startup: ", e);
108-
e.printStackTrace();
109-
System.exit(1);
110-
return null; // unreachable, but required to compile
81+
82+
@Override
83+
public void start() {
84+
LOG.info("Starting Samba plugin");
85+
if (startingTasksDone.compareAndSet(false, true)) {
86+
SambaSDK sdk = this.initSamba();
87+
sambaSDKFuture.complete(sdk);
88+
this.metricsSystemService = this.getBesuService(this.serviceManager, MetricsSystem.class);
89+
}
90+
}
91+
92+
@Override
93+
public void stop() {
94+
LOG.info("Stopping Samba plugin");
95+
registrationTaskDone.set(false);
96+
startingTasksDone.set(false);
97+
this.besuConfigurationService = null;
98+
this.metricCategoryRegistryService = null;
99+
this.rpcEndpointService = null;
100+
this.picoCLIOptionsService = null;
101+
// TODO should we do something with Samba | its db ?
102+
// TODO call samba to stop
103+
}
104+
105+
private SambaSDK initSamba() {
106+
try {
107+
String[] options = {
108+
"--portal-subnetworks=history-network",
109+
"--p2p-advertised-ip=" + host,
110+
"--disable-json-rpc-server",
111+
"--disable-rest--server",
112+
"--logging=" + loggingLevel,
113+
"--data-path=" + dataPath
114+
};
115+
return Samba.init(options);
116+
117+
} catch (Exception e) {
118+
LOG.error("Halting Besu startup: exception in plugin startup: ", e);
119+
e.printStackTrace();
120+
System.exit(1);
121+
return null; // unreachable, but required to compile
122+
}
123+
}
124+
125+
private void starRpcEndpoints() {
126+
var methods = List.of(new GetBlockBodyByBlockHash(this.sambaSDKFuture),
127+
new GetBlockHeaderByBlockHash(this.sambaSDKFuture),
128+
new GetTransactionReceiptByBlockHash(this.sambaSDKFuture),
129+
new GetTransactionReceiptByBlockHash(this.sambaSDKFuture));
130+
methods.forEach(
131+
method -> {
132+
LOG.info(
133+
"Registering RPC plugin endpoint {}_{}", method.getNamespace(), method.getName());
134+
rpcEndpointService.registerRPCEndpoint(
135+
method.getNamespace(), method.getName(), method::execute);
136+
});
137+
}
138+
139+
private <T extends BesuService> T getBesuService(ServiceManager context, Class<T> clazz) {
140+
return context
141+
.getService(clazz)
142+
.orElseThrow(
143+
() ->
144+
new RuntimeException(
145+
"Unable to find given Besu service. Please ensure %s is registered."
146+
.formatted(clazz.getName())));
147+
}
148+
149+
150+
@Override
151+
public Optional<BlockHeader> getBlockHeaderByBlockHash(Hash blockHash) {
152+
try {
153+
return this.sambaSDKFuture
154+
.get().historyAPI().flatMap(history -> history.getBlockHeaderByBlockHash(blockHash));
155+
} catch (InterruptedException | ExecutionException e) {
156+
LOG.debug("Error when executing GetBlockHeaderByBlockHash operation");
157+
}
158+
return Optional.empty();
159+
}
160+
161+
@Override
162+
public Optional<BlockBody> getBlockBodyByBlockHash(Hash blockHash) {
163+
try {
164+
return this.sambaSDKFuture.get()
165+
.historyAPI()
166+
.flatMap(history -> history.getBlockBodyByBlockHash(blockHash));
167+
} catch (InterruptedException | ExecutionException e) {
168+
LOG.debug("Error when executing GetBlockBodyByBlockHash operation");
169+
}
170+
return Optional.empty();
171+
}
172+
173+
@Override
174+
public Optional<List<TransactionReceipt>> getTransactionReceiptByBlockHash(Hash blockHash) {
175+
try {
176+
return this.sambaSDKFuture.get().historyAPI().flatMap(history -> history.getTransactionReceiptByBlockHash(blockHash));
177+
} catch (InterruptedException | ExecutionException e) {
178+
LOG.debug("Error when executing GetTransactionReceiptByBlockHash operation");
179+
}
180+
return Optional.empty();
111181
}
112-
}
113-
114-
private void starRpcEndpoints() {
115-
var methods = List.of(new GetBlockBodyByBlockHash(this.sambaSDKFuture));
116-
methods.forEach(
117-
method -> {
118-
LOG.info(
119-
"Registering RPC plugin endpoint {}_{}", method.getNamespace(), method.getName());
120-
rpcEndpointService.registerRPCEndpoint(
121-
method.getNamespace(), method.getName(), method::execute);
122-
});
123-
}
124-
125-
private <T extends BesuService> T getBesuService(ServiceManager context, Class<T> clazz) {
126-
return context
127-
.getService(clazz)
128-
.orElseThrow(
129-
() ->
130-
new RuntimeException(
131-
"Unable to find given Besu service. Please ensure %s is registered."
132-
.formatted(clazz.getName())));
133-
}
134-
}
135182

136-
/*
137-
@Override
138-
public Optional<BlockHeader> getBlockHeaderByBlockHash(Hash blockHash) {
139-
return this.sambaSDK
140-
.historyAPI()
141-
.flatMap(history -> history.getBlockHeaderByBlockHash(blockHash));
142-
}
143-
144-
@Override
145-
public Optional<BlockBody> getBlockBodyByBlockHash(Hash blockHash) {
146-
return this.sambaSDK
147-
.historyAPI()
148-
.flatMap(history -> history.getBlockBodyByBlockHash(blockHash));
149-
}
150-
151-
@Override
152-
public Optional<List<TransactionReceipt>> getTransactionReceiptByBlockHash(Hash blockHash) {
153-
return this.sambaSDK.historyAPI().flatMap(history -> history.getReceiptByBlockHash(blockHash));
154-
}
155-
156-
@Override
157-
public Optional<BlockHeader> getBlockHeaderByBlockNumber(long blockNumber) {
158-
return this.sambaSDK
159-
.historyAPI()
160-
.flatMap(history -> history.getBlockHeaderByBlockNumber(blockNumber));
161-
}
183+
@Override
184+
public Optional<BlockHeader> getBlockHeaderByBlockNumber(String blockNumber) {
185+
try {
186+
return this.sambaSDKFuture.get()
187+
.historyAPI()
188+
.flatMap(history -> history.getBlockHeaderByBlockNumber(blockNumber));
189+
} catch (InterruptedException | ExecutionException e) {
190+
LOG.debug("Error when executing GetBlockHeaderByBlockNumber operation");
191+
}
192+
return Optional.empty();
193+
}
162194
}
163-
*/
195+

besu-plugin/core/src/main/java/samba/api/HistoryService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ public interface HistoryService {
1818

1919
Optional<List<TransactionReceipt>> getTransactionReceiptByBlockHash(Hash blockHash);
2020

21-
Optional<BlockHeader> getBlockHeaderByBlockNumber(long blockNumber);
21+
//The characters in the string must all be decimal digits
22+
Optional<BlockHeader> getBlockHeaderByBlockNumber(String blockNumber);
2223
}

besu-plugin/core/src/main/java/samba/rpc/GetBlockBodyByBlockHash.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import org.hyperledger.besu.datatypes.Hash;
77
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter;
8-
import org.hyperledger.besu.ethereum.core.BlockHeader;
8+
import org.hyperledger.besu.ethereum.core.BlockBody;
99
import org.hyperledger.besu.plugin.services.rpc.PluginRpcRequest;
1010
import samba.BesuSambaPlugin;
1111
import samba.SambaSDK;
@@ -25,7 +25,7 @@ public String getNamespace() {
2525

2626
@Override
2727
public String getName() {
28-
return RpcMethod.GET_BLOCK_BODY_BY_HASH.getMethodName();
28+
return RpcMethod.GET_BLOCK_BODY_BY_BLOCK_HASH.getMethodName();
2929
}
3030

3131
@Override
@@ -36,8 +36,8 @@ public Object execute(PluginRpcRequest rpcRequest) {
3636
return this.sambaSDKFuture
3737
.get()
3838
.historyAPI()
39-
.flatMap(history -> history.getBlockHeaderByBlockHash(blockHash))
40-
.map(BlockHeader::toString)
39+
.flatMap(history -> history.getBlockBodyByBlockHash(blockHash))
40+
.map(BlockBody::toString)
4141
.orElse("");
4242
} catch (JsonRpcParameter.JsonRpcParameterException
4343
| ExecutionException

0 commit comments

Comments
 (0)