surfpool_core/rpc/admin.rs
1use std::{
2 collections::HashMap,
3 net::SocketAddr,
4 time::{Duration, SystemTime},
5};
6
7use jsonrpc_core::{BoxFuture, Result};
8use jsonrpc_derive::rpc;
9use solana_client::{rpc_config::RpcAccountIndex, rpc_custom_error::RpcCustomError};
10use solana_pubkey::Pubkey;
11use surfpool_types::SimnetCommand;
12use txtx_addon_network_svm_types::subgraph::PluginConfig;
13use uuid::Uuid;
14
15use super::{not_implemented_err, not_implemented_err_async, RunloopContext};
16use crate::PluginManagerCommand;
17
18#[rpc]
19pub trait AdminRpc {
20 type Metadata;
21
22 /// Immediately shuts down the RPC server.
23 ///
24 /// This administrative endpoint is typically used during controlled shutdowns of the validator
25 /// or service exposing the RPC interface. It allows remote administrators to gracefully terminate
26 /// the process, stopping all RPC activity.
27 ///
28 /// ## Returns
29 /// - [`Result<()>`] — A unit result indicating successful shutdown, or an error if the call fails.
30 ///
31 /// ## Example Request (JSON-RPC)
32 /// ```json
33 /// {
34 /// "jsonrpc": "2.0",
35 /// "id": 42,
36 /// "method": "exit",
37 /// "params": []
38 /// }
39 /// ```
40 ///
41 /// # Notes
42 /// - This method is privileged and should only be accessible to trusted clients.
43 /// - Use with extreme caution in production environments.
44 /// - If successful, the RPC server process will terminate immediately after processing this call.
45 ///
46 /// # Security
47 /// Access to this method should be tightly restricted. Implement proper authorization mechanisms
48 /// via the RPC metadata to prevent accidental or malicious use.
49 #[rpc(meta, name = "exit")]
50 fn exit(&self, meta: Self::Metadata) -> Result<()>;
51
52 #[rpc(meta, name = "reloadPlugin")]
53 fn reload_plugin(
54 &self,
55 meta: Self::Metadata,
56 name: String,
57 config_file: String,
58 ) -> BoxFuture<Result<()>>;
59
60 /// Reloads a runtime plugin with new configuration.
61 ///
62 /// This administrative endpoint is used to dynamically reload a plugin without restarting
63 /// the entire RPC server or validator. It is useful for applying updated configurations
64 /// to a plugin that supports hot-reloading.
65 ///
66 /// ## Parameters
67 /// - `name`: The identifier of the plugin to reload.
68 /// - `config_file`: Path to the new configuration file to load for the plugin.
69 ///
70 /// ## Returns
71 /// - [`BoxFuture<Result<()>>`] — A future resolving to a unit result on success, or an error if
72 /// reloading fails.
73 ///
74 /// ## Example Request (JSON-RPC)
75 /// ```json
76 /// {
77 /// "jsonrpc": "2.0",
78 /// "id": 101,
79 /// "method": "reloadPlugin",
80 /// "params": ["myPlugin", "/etc/plugins/my_plugin_config.toml"]
81 /// }
82 /// ```
83 ///
84 /// # Notes
85 /// - The plugin must support reloading in order for this to succeed.
86 /// - A failed reload will leave the plugin in its previous state.
87 /// - This method is intended for administrators and should be properly secured.
88 ///
89 /// # Security
90 /// Ensure only trusted clients can invoke this method. Use metadata-based access control to limit exposure.
91 #[rpc(meta, name = "unloadPlugin")]
92 fn unload_plugin(&self, meta: Self::Metadata, name: String) -> BoxFuture<Result<()>>;
93
94 /// Dynamically loads a new plugin into the runtime from a configuration file.
95 ///
96 /// This administrative endpoint is used to add a new plugin to the system at runtime,
97 /// based on the configuration provided. It enables extensibility without restarting
98 /// the validator or RPC server.
99 ///
100 /// ## Parameters
101 /// - `config_file`: Path to the plugin's configuration file, which defines its behavior and settings.
102 ///
103 /// ## Returns
104 /// - [`BoxFuture<Result<String>>`] — A future resolving to the name or identifier of the loaded plugin,
105 /// or an error if the plugin could not be loaded.
106 ///
107 /// ## Example Request (JSON-RPC)
108 /// ```json
109 /// {
110 /// "jsonrpc": "2.0",
111 /// "id": 102,
112 /// "method": "loadPlugin",
113 /// "params": ["/etc/plugins/my_plugin_config.toml"]
114 /// }
115 /// ```
116 ///
117 /// # Notes
118 /// - The plugin system must be initialized and support runtime loading.
119 /// - The config file should be well-formed and point to a valid plugin implementation.
120 /// - Duplicate plugin names may lead to conflicts or errors.
121 ///
122 /// # Security
123 /// This method should be restricted to administrators only. Validate inputs and use access control.
124 #[rpc(meta, name = "loadPlugin")]
125 fn load_plugin(&self, meta: Self::Metadata, config_file: String) -> BoxFuture<Result<String>>;
126
127 /// Returns a list of all currently loaded plugin names.
128 ///
129 /// This administrative RPC method is used to inspect which plugins have been successfully
130 /// loaded into the runtime. It can be useful for debugging or operational monitoring.
131 ///
132 /// ## Returns
133 /// - `Vec<String>` — A list of plugin names currently active in the system.
134 ///
135 /// ## Example Request (JSON-RPC)
136 /// ```json
137 /// {
138 /// "jsonrpc": "2.0",
139 /// "id": 103,
140 /// "method": "listPlugins",
141 /// "params": []
142 /// }
143 /// ```
144 ///
145 /// ## Example Response
146 /// ```json
147 /// {
148 /// "jsonrpc": "2.0",
149 /// "result": ["tx_filter", "custom_logger"],
150 /// "id": 103
151 /// }
152 /// ```
153 ///
154 /// # Notes
155 /// - Only plugins that have been successfully loaded will appear in this list.
156 /// - This method is read-only and safe to call frequently.
157 #[rpc(meta, name = "listPlugins")]
158 fn list_plugins(&self, meta: Self::Metadata) -> BoxFuture<Result<Vec<String>>>;
159
160 /// Returns the address of the RPC server.
161 ///
162 /// This RPC method retrieves the network address (IP and port) the RPC server is currently
163 /// listening on. It can be useful for service discovery or monitoring the server’s network status.
164 ///
165 /// ## Returns
166 /// - `Option<SocketAddr>` — The network address of the RPC server, or `None` if no address is available.
167 ///
168 /// ## Example Request (JSON-RPC)
169 /// ```json
170 /// {
171 /// "jsonrpc": "2.0",
172 /// "id": 104,
173 /// "method": "rpcAddress",
174 /// "params": []
175 /// }
176 /// ```
177 ///
178 /// ## Example Response
179 /// ```json
180 /// {
181 /// "jsonrpc": "2.0",
182 /// "result": "127.0.0.1:8080",
183 /// "id": 104
184 /// }
185 /// ```
186 ///
187 /// # Notes
188 /// - This method is useful for finding the address of a running RPC server, especially in dynamic environments.
189 /// - If the server is not configured or is running without network exposure, the result may be `None`.
190 #[rpc(meta, name = "rpcAddress")]
191 fn rpc_addr(&self, meta: Self::Metadata) -> Result<Option<SocketAddr>>;
192
193 /// Sets a filter for log messages in the system.
194 ///
195 /// This RPC method allows the user to configure the logging level or filters applied to the logs
196 /// generated by the system. It enables fine-grained control over which log messages are captured
197 /// and how they are displayed or stored.
198 ///
199 /// ## Parameters
200 /// - `filter`: A string representing the desired log filter. This could be a log level (e.g., `info`, `debug`, `error`),
201 /// or a more complex filter expression depending on the system’s logging configuration.
202 ///
203 /// ## Returns
204 /// - `()` — A unit result indicating the operation was successful.
205 ///
206 /// ## Example Request (JSON-RPC)
207 /// ```json
208 /// {
209 /// "jsonrpc": "2.0",
210 /// "id": 105,
211 /// "method": "setLogFilter",
212 /// "params": ["debug"]
213 /// }
214 /// ```
215 ///
216 /// ## Example Response
217 /// ```json
218 /// {
219 /// "jsonrpc": "2.0",
220 /// "result": null,
221 /// "id": 105
222 /// }
223 /// ```
224 ///
225 /// # Notes
226 /// - The `filter` parameter should be consistent with the logging framework used by the system.
227 /// - Valid filter values might include common log levels such as `trace`, `debug`, `info`, `warn`, `error`, or other custom filters.
228 /// - This method allows dynamic control of the log output, so it should be used cautiously in production environments.
229 #[rpc(name = "setLogFilter")]
230 fn set_log_filter(&self, filter: String) -> Result<()>;
231
232 /// Returns the system start time.
233 ///
234 /// This RPC method retrieves the timestamp of when the system was started, represented as
235 /// a `SystemTime`. It can be useful for measuring uptime or for tracking the system's runtime
236 /// in logs or monitoring systems.
237 ///
238 /// ## Returns
239 /// - `SystemTime` — The timestamp representing when the system was started.
240 ///
241 /// ## Example Request (JSON-RPC)
242 /// ```json
243 /// {
244 /// "jsonrpc": "2.0",
245 /// "id": 106,
246 /// "method": "startTime",
247 /// "params": []
248 /// }
249 /// ```
250 ///
251 /// ## Example Response
252 /// ```json
253 /// {
254 /// "jsonrpc": "2.0",
255 /// "result": "2025-04-24T12:34:56Z",
256 /// "id": 106
257 /// }
258 /// ```
259 ///
260 /// # Notes
261 /// - The result is a `SystemTime` in UTC, reflecting the moment the system was initialized.
262 /// - This method is useful for monitoring system uptime and verifying system health.
263 #[rpc(meta, name = "startTime")]
264 fn start_time(&self, meta: Self::Metadata) -> Result<SystemTime>;
265
266 // #[rpc(meta, name = "startProgress")]
267 // fn start_progress(&self, meta: Self::Metadata) -> Result<ValidatorStartProgress>;
268
269 /// Adds an authorized voter to the system.
270 ///
271 /// This RPC method allows an authorized user to add a new voter to the list of authorized
272 /// voters. A voter is typically an entity that can participate in governance actions, such as
273 /// voting on proposals or other decision-making processes.
274 ///
275 /// ## Parameters
276 /// - `keypair_file`: A string representing the path to the file containing the keypair of the new voter.
277 /// The keypair is used to authenticate and authorize the voter to participate in governance.
278 ///
279 /// ## Returns
280 /// - `()` — A unit result indicating that the operation was successful.
281 ///
282 /// ## Example Request (JSON-RPC)
283 /// ```json
284 /// {
285 /// "jsonrpc": "2.0",
286 /// "id": 107,
287 /// "method": "addAuthorizedVoter",
288 /// "params": ["path/to/voter_keypair.json"]
289 /// }
290 /// ```
291 ///
292 /// ## Example Response
293 /// ```json
294 /// {
295 /// "jsonrpc": "2.0",
296 /// "result": null,
297 /// "id": 107
298 /// }
299 /// ```
300 ///
301 /// # Notes
302 /// - This method typically requires administrative or elevated permissions to execute.
303 /// - The `keypair_file` should contain a valid keypair for the new voter, formatted according to the system's expectations.
304 /// - Once added, the new voter will be able to participate in governance actions.
305 #[rpc(meta, name = "addAuthorizedVoter")]
306 fn add_authorized_voter(&self, meta: Self::Metadata, keypair_file: String) -> Result<()>;
307
308 /// Adds an authorized voter to the system using a byte-encoded keypair.
309 ///
310 /// This RPC method allows an authorized user to add a new voter by directly providing the
311 /// keypair in the form of a byte vector (`Vec<u8>`). This can be useful for systems where keypairs
312 /// are serialized or passed in a non-file-based format.
313 ///
314 /// ## Parameters
315 /// - `keypair`: A vector of bytes representing the keypair of the new voter. This keypair will be used to
316 /// authenticate and authorize the voter to participate in governance actions.
317 ///
318 /// ## Returns
319 /// - `()` — A unit result indicating the operation was successful.
320 ///
321 /// ## Example Request (JSON-RPC)
322 /// ```json
323 /// {
324 /// "jsonrpc": "2.0",
325 /// "id": 108,
326 /// "method": "addAuthorizedVoterFromBytes",
327 /// "params": ["<base64-encoded-keypair>"]
328 /// }
329 /// ```
330 ///
331 /// ## Example Response
332 /// ```json
333 /// {
334 /// "jsonrpc": "2.0",
335 /// "result": null,
336 /// "id": 108
337 /// }
338 /// ```
339 ///
340 /// # Notes
341 /// - This method allows for adding a voter directly from a byte-encoded keypair, which may be useful for
342 /// systems that store keypairs in non-traditional formats (e.g., databases, serialized data).
343 /// - The `keypair` should be provided in the correct format expected by the system (typically a base64 or raw binary format).
344 /// - This method typically requires administrative or elevated permissions to execute.
345 /// - Once added, the new voter will be able to participate in governance actions.
346 #[rpc(meta, name = "addAuthorizedVoterFromBytes")]
347 fn add_authorized_voter_from_bytes(&self, meta: Self::Metadata, keypair: Vec<u8>)
348 -> Result<()>;
349
350 /// Removes all authorized voters from the system.
351 ///
352 /// This RPC method removes all voters from the list of authorized voters. This action
353 /// is typically an administrative function and may be used to reset or clean up the list of
354 /// voters in the system.
355 ///
356 /// ## Parameters
357 /// - None.
358 ///
359 /// ## Returns
360 /// - `()` — A unit result indicating that the operation was successful.
361 ///
362 /// ## Example Request (JSON-RPC)
363 /// ```json
364 /// {
365 /// "jsonrpc": "2.0",
366 /// "id": 109,
367 /// "method": "removeAllAuthorizedVoters",
368 /// "params": []
369 /// }
370 /// ```
371 ///
372 /// ## Example Response
373 /// ```json
374 /// {
375 /// "jsonrpc": "2.0",
376 /// "result": null,
377 /// "id": 109
378 /// }
379 /// ```
380 ///
381 /// # Notes
382 /// - This method will remove all voters and may not be reversible. It is a critical operation that
383 /// typically requires elevated administrative permissions.
384 /// - Use this method with caution as it will prevent any previously authorized voter from participating
385 /// in governance actions until they are re-added.
386 #[rpc(meta, name = "removeAllAuthorizedVoters")]
387 fn remove_all_authorized_voters(&self, meta: Self::Metadata) -> Result<()>;
388
389 /// Sets the identity for the system using the provided keypair.
390 ///
391 /// This RPC method allows you to set the system's identity by specifying a keypair file.
392 /// The identity set here is typically used to authenticate the system and validate its
393 /// actions in governance or other sensitive operations. The `require_tower` flag ensures
394 /// that a specific security feature, called "tower," is enabled for the identity.
395 ///
396 /// ## Parameters
397 /// - `keypair_file`: The file path to the keypair that will be used to set the system's identity.
398 /// - `require_tower`: A boolean flag indicating whether the tower security feature should be enforced
399 /// for this identity.
400 ///
401 /// ## Returns
402 /// - `()` — A unit result indicating that the operation was successful.
403 ///
404 /// ## Example Request (JSON-RPC)
405 /// ```json
406 /// {
407 /// "jsonrpc": "2.0",
408 /// "id": 110,
409 /// "method": "setIdentity",
410 /// "params": ["/path/to/keypair.json", true]
411 /// }
412 /// ```
413 ///
414 /// ## Example Response
415 /// ```json
416 /// {
417 /// "jsonrpc": "2.0",
418 /// "result": null,
419 /// "id": 110
420 /// }
421 /// ```
422 ///
423 /// # Notes
424 /// - This method allows for setting the identity of the system, which could have security and governance
425 /// implications. It is typically used when initializing or reconfiguring the system's identity.
426 /// - The `require_tower` flag is optional but can be used to add an extra layer of security for the identity.
427 /// - The method usually requires administrative permissions and a valid keypair to execute.
428 #[rpc(meta, name = "setIdentity")]
429 fn set_identity(
430 &self,
431 meta: Self::Metadata,
432 keypair_file: String,
433 require_tower: bool,
434 ) -> Result<()>;
435
436 /// Sets the identity for the system using a keypair provided as a byte array.
437 ///
438 /// This RPC method allows you to set the system's identity by directly providing a byte array
439 /// representing the keypair. The `require_tower` flag is used to enforce the "tower" security feature
440 /// for this identity, if needed.
441 ///
442 /// ## Parameters
443 /// - `identity_keypair`: A byte array representing the keypair to set the system's identity.
444 /// - `require_tower`: A boolean flag indicating whether the tower security feature should be enforced
445 /// for this identity.
446 ///
447 /// ## Returns
448 /// - `()` — A unit result indicating that the operation was successful.
449 ///
450 /// ## Example Request (JSON-RPC)
451 /// ```json
452 /// {
453 /// "jsonrpc": "2.0",
454 /// "id": 111,
455 /// "method": "setIdentityFromBytes",
456 /// "params": [[72, 101, 108, 108, 111], true]
457 /// }
458 /// ```
459 ///
460 /// ## Example Response
461 /// ```json
462 /// {
463 /// "jsonrpc": "2.0",
464 /// "result": null,
465 /// "id": 111
466 /// }
467 /// ```
468 ///
469 /// # Notes
470 /// - This method is useful for scenarios where the keypair is not stored in a file but is instead available
471 /// as a byte array (e.g., for programmatically generated keypairs).
472 /// - The `require_tower` flag, when set to `true`, enforces additional security for the identity.
473 /// - The method typically requires administrative permissions to execute.
474 #[rpc(meta, name = "setIdentityFromBytes")]
475 fn set_identity_from_bytes(
476 &self,
477 meta: Self::Metadata,
478 identity_keypair: Vec<u8>,
479 require_tower: bool,
480 ) -> Result<()>;
481
482 /// Sets the overrides for staked nodes using a specified path.
483 ///
484 /// This RPC method allows you to configure overrides for staked nodes by specifying the path
485 /// to a configuration file. This is typically used for adjusting the parameters or behavior
486 /// of the staked nodes in the system, such as custom settings for node management or staking
487 /// operations.
488 ///
489 /// ## Parameters
490 /// - `path`: The file path to the configuration file that contains the staked node overrides.
491 /// This file should define the necessary settings for overriding the default staked node configuration.
492 ///
493 /// ## Returns
494 /// - `()` — A unit result indicating that the operation was successful.
495 ///
496 /// ## Example Request (JSON-RPC)
497 /// ```json
498 /// {
499 /// "jsonrpc": "2.0",
500 /// "id": 112,
501 /// "method": "setStakedNodesOverrides",
502 /// "params": ["/path/to/overrides.json"]
503 /// }
504 /// ```
505 ///
506 /// ## Example Response
507 /// ```json
508 /// {
509 /// "jsonrpc": "2.0",
510 /// "result": null,
511 /// "id": 112
512 /// }
513 /// ```
514 ///
515 /// # Notes
516 /// - This method is used for overriding the configuration of staked nodes in the system.
517 /// The `path` parameter should point to a file that contains the necessary overrides.
518 /// - It may require administrative permissions to modify the staked node configurations.
519 /// - The path file should be in a format understood by the system (e.g., JSON, YAML).
520 #[rpc(meta, name = "setStakedNodesOverrides")]
521 fn set_staked_nodes_overrides(&self, meta: Self::Metadata, path: String) -> Result<()>;
522
523 /// Repairs a shred from a peer node in the network.
524 ///
525 /// This RPC method triggers the repair of a specific shred from a peer node, using the given
526 /// `pubkey` (if provided), `slot`, and `shred_index`. This is typically used in cases where
527 /// a shred is missing or corrupted and needs to be retrieved from another node in the network.
528 ///
529 /// ## Parameters
530 /// - `pubkey` (Optional): The public key of the node from which to request the shred. If `None`,
531 /// the system may choose any peer to attempt the repair from.
532 /// - `slot`: The slot number where the shred is located.
533 /// - `shred_index`: The index of the specific shred within the given slot that needs repair.
534 ///
535 /// ## Returns
536 /// - `()` — A unit result indicating that the operation was successful.
537 ///
538 /// ## Example Request (JSON-RPC)
539 /// ```json
540 /// {
541 /// "jsonrpc": "2.0",
542 /// "id": 113,
543 /// "method": "repairShredFromPeer",
544 /// "params": ["PubkeyHere", 12345, 6789]
545 /// }
546 /// ```
547 ///
548 /// ## Example Response
549 /// ```json
550 /// {
551 /// "jsonrpc": "2.0",
552 /// "result": null,
553 /// "id": 113
554 /// }
555 /// ```
556 ///
557 /// # Notes
558 /// - The method may require specific network configurations or permissions to allow for the repair of the shred.
559 /// - If the `pubkey` is provided, the system will attempt to retrieve the shred from the specified peer node. Otherwise,
560 /// it will attempt the repair from any available node in the network.
561 #[rpc(meta, name = "repairShredFromPeer")]
562 fn repair_shred_from_peer(
563 &self,
564 meta: Self::Metadata,
565 pubkey: Option<Pubkey>,
566 slot: u64,
567 shred_index: u64,
568 ) -> Result<()>;
569
570 /// Sets the whitelist of nodes allowed to repair shreds.
571 ///
572 /// This RPC method sets a list of nodes (identified by their public keys) that are permitted
573 /// to repair shreds in the network. The whitelist controls which nodes have the authority to
574 /// perform repairs. Any node not included in the whitelist will be restricted from initiating
575 /// shred repair operations.
576 ///
577 /// ## Parameters
578 /// - `whitelist`: A vector of `Pubkey` values representing the public keys of the nodes
579 /// that are authorized to repair shreds.
580 ///
581 /// ## Returns
582 /// - `()` — A unit result indicating that the operation was successful.
583 ///
584 /// ## Example Request (JSON-RPC)
585 /// ```json
586 /// {
587 /// "jsonrpc": "2.0",
588 /// "id": 114,
589 /// "method": "setRepairWhitelist",
590 /// "params": [["Pubkey1", "Pubkey2", "Pubkey3"]]
591 /// }
592 /// ```
593 ///
594 /// ## Example Response
595 /// ```json
596 /// {
597 /// "jsonrpc": "2.0",
598 /// "result": null,
599 /// "id": 114
600 /// }
601 /// ```
602 ///
603 /// # Notes
604 /// - This method is generally used by network administrators to control which nodes are trusted
605 /// to perform repairs on the network.
606 /// - The whitelist ensures that only authorized nodes can engage in potentially sensitive network repair actions.
607 #[rpc(meta, name = "setRepairWhitelist")]
608 fn set_repair_whitelist(&self, meta: Self::Metadata, whitelist: Vec<Pubkey>) -> Result<()>;
609
610 /// Retrieves the size of the secondary index key for a given account.
611 ///
612 /// This RPC method returns the size of the secondary index key associated with a specific
613 /// account, identified by its public key. The secondary index key is used in the indexing
614 /// mechanism to quickly access account-related data.
615 ///
616 /// ## Parameters
617 /// - `pubkey_str`: A string representing the public key of the account for which the
618 /// secondary index key size is being queried.
619 ///
620 /// ## Returns
621 /// - `HashMap<RpcAccountIndex, usize>`: A mapping of account indices to their respective key sizes.
622 ///
623 /// ## Example Request (JSON-RPC)
624 /// ```json
625 /// {
626 /// "jsonrpc": "2.0",
627 /// "id": 115,
628 /// "method": "getSecondaryIndexKeySize",
629 /// "params": ["PubkeyString"]
630 /// }
631 /// ```
632 ///
633 /// ## Example Response
634 /// ```json
635 /// {
636 /// "jsonrpc": "2.0",
637 /// "result": {
638 /// "programId": 128,
639 /// "splTokenMint": 256,
640 /// "splTokenOwner": 192
641 /// },
642 /// "id": 115
643 /// }
644 /// ```
645 ///
646 /// # Notes
647 /// - The returned `HashMap` will contain index types as keys, and the size of each key
648 #[rpc(meta, name = "getSecondaryIndexKeySize")]
649 fn get_secondary_index_key_size(
650 &self,
651 meta: Self::Metadata,
652 pubkey_str: String,
653 ) -> Result<HashMap<RpcAccountIndex, usize>>;
654
655 /// Sets the public TPU (Transaction Processing Unit) address.
656 ///
657 /// This RPC method is used to configure the public TPU address of the node. The TPU address
658 /// is used for communication between the validator and the network, allowing the node to
659 /// send and receive transactions.
660 ///
661 /// ## Parameters
662 /// - `public_tpu_addr`: A `SocketAddr` representing the public TPU address to be set.
663 ///
664 /// ## Returns
665 /// - `Result<()>`: Returns `Ok(())` if the operation was successful, or an error if
666 /// there was an issue setting the TPU address.
667 ///
668 /// ## Example Request (JSON-RPC)
669 /// ```json
670 /// {
671 /// "jsonrpc": "2.0",
672 /// "id": 118,
673 /// "method": "setPublicTpuAddress",
674 /// "params": ["127.0.0.1:8000"]
675 /// }
676 /// ```
677 ///
678 /// ## Example Response
679 /// ```json
680 /// {
681 /// "jsonrpc": "2.0",
682 /// "result": null,
683 /// "id": 118
684 /// }
685 /// ```
686 ///
687 /// # Notes
688 /// - The TPU address is important for a validator node to participate in transaction
689 /// processing and communication with the rest of the Solana network.
690 /// - This method is typically used to configure the node's external-facing address, allowing
691 /// it to communicate with clients or other validators.
692 ///
693 /// ## Errors
694 /// - If the provided address is invalid or there is a failure when setting the address,
695 /// an error will be returned.
696 #[rpc(meta, name = "setPublicTpuAddress")]
697 fn set_public_tpu_address(
698 &self,
699 meta: Self::Metadata,
700 public_tpu_addr: SocketAddr,
701 ) -> Result<()>;
702
703 /// Sets the public TPU forwards address.
704 ///
705 /// This RPC method configures the public address for TPU forwarding. It is used to specify
706 /// a separate address for forwarding transactions to a different destination, often used
707 /// for specialized network configurations or load balancing.
708 ///
709 /// ## Parameters
710 /// - `public_tpu_forwards_addr`: A `SocketAddr` representing the public TPU forwards
711 /// address to be set.
712 ///
713 /// ## Returns
714 /// - `Result<()>`: Returns `Ok(())` if the operation was successful, or an error if
715 /// there was an issue setting the TPU forwards address.
716 ///
717 /// ## Example Request (JSON-RPC)
718 /// ```json
719 /// {
720 /// "jsonrpc": "2.0",
721 /// "id": 118,
722 /// "method": "setPublicTpuForwardsAddress",
723 /// "params": ["127.0.0.1:9000"]
724 /// }
725 /// ```
726 ///
727 /// ## Example Response
728 /// ```json
729 /// {
730 /// "jsonrpc": "2.0",
731 /// "result": null,
732 /// "id": 118
733 /// }
734 /// ```
735 ///
736 /// # Notes
737 /// - This method is typically used for advanced network configurations, where a node might
738 /// want to forward its transaction processing requests to another address.
739 /// - The provided `SocketAddr` should be valid and reachable.
740 ///
741 /// ## Errors
742 /// - If the provided address is invalid or there is a failure when setting the address,
743 /// an error will be returned.
744 #[rpc(meta, name = "setPublicTpuForwardsAddress")]
745 fn set_public_tpu_forwards_address(
746 &self,
747 meta: Self::Metadata,
748 public_tpu_forwards_addr: SocketAddr,
749 ) -> Result<()>;
750}
751
752pub struct SurfpoolAdminRpc;
753impl AdminRpc for SurfpoolAdminRpc {
754 type Metadata = Option<RunloopContext>;
755
756 fn exit(&self, meta: Self::Metadata) -> Result<()> {
757 let Some(ctx) = meta else {
758 return Err(RpcCustomError::NodeUnhealthy {
759 num_slots_behind: None,
760 }
761 .into());
762 };
763
764 let _ = ctx
765 .simnet_commands_tx
766 .send(SimnetCommand::Terminate(ctx.id));
767
768 Ok(())
769 }
770
771 fn reload_plugin(
772 &self,
773 _meta: Self::Metadata,
774 _name: String,
775 _config_file: String,
776 ) -> BoxFuture<Result<()>> {
777 not_implemented_err_async("reload_plugin")
778 }
779
780 fn unload_plugin(&self, _meta: Self::Metadata, _name: String) -> BoxFuture<Result<()>> {
781 not_implemented_err_async("unload_plugin")
782 }
783
784 fn load_plugin(&self, meta: Self::Metadata, config_file: String) -> BoxFuture<Result<String>> {
785 let config = match serde_json::from_str::<PluginConfig>(&config_file)
786 .map_err(|e| format!("failed to deserialize plugin config: {e}"))
787 {
788 Ok(config) => config,
789 Err(e) => return Box::pin(async move { Err(jsonrpc_core::Error::invalid_params(&e)) }),
790 };
791 let ctx = meta.unwrap();
792 let uuid = Uuid::new_v4();
793 let (tx, rx) = crossbeam_channel::bounded(1);
794 let _ = ctx
795 .plugin_manager_commands_tx
796 .send(PluginManagerCommand::LoadConfig(uuid, config, tx));
797
798 let Ok(endpoint_url) = rx.recv_timeout(Duration::from_secs(10)) else {
799 return Box::pin(async move { Err(jsonrpc_core::Error::internal_error()) });
800 };
801 Box::pin(async move { Ok(endpoint_url) })
802 }
803
804 fn list_plugins(&self, _meta: Self::Metadata) -> BoxFuture<Result<Vec<String>>> {
805 not_implemented_err_async("list_plugins")
806 }
807
808 fn rpc_addr(&self, _meta: Self::Metadata) -> Result<Option<SocketAddr>> {
809 not_implemented_err("rpc_addr")
810 }
811
812 fn set_log_filter(&self, _filter: String) -> Result<()> {
813 not_implemented_err("set_log_filter")
814 }
815
816 fn start_time(&self, _meta: Self::Metadata) -> Result<SystemTime> {
817 not_implemented_err("start_time")
818 }
819
820 fn add_authorized_voter(&self, _meta: Self::Metadata, _keypair_file: String) -> Result<()> {
821 not_implemented_err("add_authorized_voter")
822 }
823
824 fn add_authorized_voter_from_bytes(
825 &self,
826 _meta: Self::Metadata,
827 _keypair: Vec<u8>,
828 ) -> Result<()> {
829 not_implemented_err("add_authorized_voter_from_bytes")
830 }
831
832 fn remove_all_authorized_voters(&self, _meta: Self::Metadata) -> Result<()> {
833 not_implemented_err("remove_all_authorized_voters")
834 }
835
836 fn set_identity(
837 &self,
838 _meta: Self::Metadata,
839 _keypair_file: String,
840 _require_tower: bool,
841 ) -> Result<()> {
842 not_implemented_err("set_identity")
843 }
844
845 fn set_identity_from_bytes(
846 &self,
847 _meta: Self::Metadata,
848 _identity_keypair: Vec<u8>,
849 _require_tower: bool,
850 ) -> Result<()> {
851 not_implemented_err("set_identity_from_bytes")
852 }
853
854 fn set_staked_nodes_overrides(&self, _meta: Self::Metadata, _path: String) -> Result<()> {
855 not_implemented_err("set_staked_nodes_overrides")
856 }
857
858 fn repair_shred_from_peer(
859 &self,
860 _meta: Self::Metadata,
861 _pubkey: Option<Pubkey>,
862 _slot: u64,
863 _shred_index: u64,
864 ) -> Result<()> {
865 not_implemented_err("repair_shred_from_peer")
866 }
867
868 fn set_repair_whitelist(&self, _meta: Self::Metadata, _whitelist: Vec<Pubkey>) -> Result<()> {
869 not_implemented_err("set_repair_whitelist")
870 }
871
872 fn get_secondary_index_key_size(
873 &self,
874 _meta: Self::Metadata,
875 _pubkey_str: String,
876 ) -> Result<HashMap<RpcAccountIndex, usize>> {
877 not_implemented_err("get_secondary_index_key_size")
878 }
879
880 fn set_public_tpu_address(
881 &self,
882 _meta: Self::Metadata,
883 _public_tpu_addr: SocketAddr,
884 ) -> Result<()> {
885 not_implemented_err("set_public_tpu_address")
886 }
887
888 fn set_public_tpu_forwards_address(
889 &self,
890 _meta: Self::Metadata,
891 _public_tpu_forwards_addr: SocketAddr,
892 ) -> Result<()> {
893 not_implemented_err("set_public_tpu_forwards_address")
894 }
895}