-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[Feature] Add Slipstream Plugin Support #4175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dgrkotsonis
wants to merge
27
commits into
staging
Choose a base branch
from
add_slipstream_plugin_support
base: staging
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
4ec2f56
first pass at plumbing for slipstream plugins
dgrkotsonis ad0c250
rework imports, fix types
dgrkotsonis 2facb89
formatting
dgrkotsonis d909f2a
fix feature flag propagation
dgrkotsonis 41c9e5e
rework flags, add some diagnostic logs
dgrkotsonis 5422f69
default features false for slipstream plugin
dgrkotsonis 9bd8bbc
update snarkVM rev, added some better logging
dgrkotsonis 6e27cfb
update snarkvm rev
dgrkotsonis 29b11b9
update snarkvm rev for testing
dgrkotsonis c23d26b
snarkvm rev with small fix
dgrkotsonis 477c019
more logs
dgrkotsonis 4cbbfc4
Updated snarkvm with arc around pluginmanager
dgrkotsonis d22be74
Update snarkvm w fewer logs
dgrkotsonis 43a5c82
updated snarkvm to hopefully avoid dynlib loading issues
dgrkotsonis 53f97ed
rebased changes, updated snarkVM, testing RPC and filtering
dgrkotsonis 75762c4
Not sure how snarkvm import got overwritten, fixing
dgrkotsonis 060b718
update with less noisy logs
dgrkotsonis 825e733
new snarkvm version with dynamic loading logs
dgrkotsonis 0ee3e70
update docs, remove reload
dgrkotsonis 989f619
Update snarkVM rev
dgrkotsonis 4923716
updated snarkvm
dgrkotsonis 05a1793
changes to account for new parking_lot rwlocks
dgrkotsonis 7ffc1aa
updated snarkvm
dgrkotsonis 2b93e75
Update with new snarkvm changes, remove slipstream service
dgrkotsonis ec83f3f
Rebased/updated, see if we can get past sync error
dgrkotsonis 3ab5120
clean up a bit
dgrkotsonis 9aaa8f4
formatting
dgrkotsonis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,181 @@ | ||
| # Slipstream Plugins | ||
|
|
||
| Slipstream is a plugin system that lets operators stream canonical mapping updates and staking | ||
| rewards from snarkOS nodes to external services (databases, metrics pipelines, etc.) in | ||
| real time, without modifying node code. | ||
|
|
||
| --- | ||
|
|
||
| ## Overview | ||
|
|
||
| Slipstream plugins are dynamically loaded shared libraries (`.so` / `.dylib` / `.dll`) that | ||
| implement the `SlipstreamPlugin` trait from `snarkvm-slipstream-plugin-interface`. The plugin | ||
| manager inside `snarkVM`'s `FinalizeStore` calls plugin hooks every time canonical finalize runs. | ||
|
|
||
| Plugins can subscribe to: | ||
|
|
||
| - **Mapping updates** — every key/value write that occurs during canonical finalize. | ||
| - **Staking rewards** — per-staker reward notifications | ||
|
|
||
| Only **Validator** and **Client** nodes finalize blocks and therefore support plugins. | ||
| Prover nodes do not. | ||
|
|
||
| --- | ||
|
|
||
| ## Building a Plugin | ||
|
|
||
| Use `snarkvm-slipstream-plugin-interface` as a dependency and implement the `SlipstreamPlugin` | ||
| trait. Compile your crate as a `cdylib`: | ||
|
|
||
| ```toml | ||
| # Cargo.toml | ||
| [lib] | ||
| crate-type = ["cdylib"] | ||
|
|
||
| [dependencies] | ||
| snarkvm-slipstream-plugin-interface = { git = "https://github.com/ProvableHQ/snarkVM.git", branch = "stream_plugin_testing" } | ||
| ``` | ||
|
|
||
| Export the constructor with the exact symbol name `_create_plugin`: | ||
|
|
||
| ```rust | ||
| #[no_mangle] | ||
| pub extern "C" fn _create_plugin() -> *mut dyn SlipstreamPlugin { | ||
| Box::into_raw(Box::new(MyPlugin::new())) | ||
| } | ||
| ``` | ||
|
|
||
| See `slipstream-plugin-postgres` in the snarkVM repository for a complete reference | ||
| implementation. | ||
|
|
||
| --- | ||
|
|
||
| ## Plugin Config File (JSON5) | ||
|
|
||
| Each plugin is configured via a JSON5 file. The required field is `libpath`, which can be | ||
| absolute or relative to the config file's directory. | ||
|
|
||
| ```json5 | ||
| { | ||
| // Required: path to the compiled .so / .dylib | ||
| libpath: "./libslipstream_postgres_example.so", | ||
|
|
||
| // Optional: override the plugin name reported by name() | ||
| name: "postgres", | ||
|
|
||
| // Plugin-specific fields (passed verbatim to on_load) | ||
| connection_string: "postgres://user:pass@localhost/aleo", | ||
| batch_size: 100, | ||
| } | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Starting a Node with Plugins | ||
|
|
||
| Compile snarkOS with the `slipstream-plugins` feature | ||
|
|
||
| ```bash | ||
| cargo build --features slipstream-plugins | ||
| ``` | ||
|
|
||
| Pass one or more `--slipstream-config` flags at startup: | ||
|
|
||
| ```bash | ||
| # Single plugin | ||
| snarkos start --client \ | ||
| --slipstream-config ~/.aleo/plugins/postgres/plugin.json5 | ||
|
|
||
| # Multiple plugins | ||
| snarkos start --validator \ | ||
| --slipstream-config ~/.aleo/plugins/postgres/plugin.json5 \ | ||
| --slipstream-config ~/.aleo/plugins/metrics/plugin.json5 | ||
| ``` | ||
|
|
||
| Plugins are loaded synchronously before the REST server starts. If any plugin fails to load, | ||
| the node exits with an error. | ||
|
|
||
| --- | ||
|
|
||
| ## Runtime Management via REST API | ||
|
|
||
| All endpoints require a valid JWT token (`Authorization: Bearer <token>`). | ||
|
|
||
| ### List loaded plugins | ||
|
|
||
| ``` | ||
| GET /{network}/slipstream/plugins | ||
| ``` | ||
|
|
||
| Response (200): | ||
| ```json | ||
| ["postgres", "metrics"] | ||
| ``` | ||
|
|
||
| ### Load a plugin at runtime | ||
|
|
||
| ``` | ||
| POST /{network}/slipstream/plugins | ||
| Content-Type: application/json | ||
|
|
||
| { "config_file": "/path/to/plugin.json5" } | ||
| ``` | ||
|
|
||
| Response (200): | ||
| ```json | ||
| { "loaded": "postgres" } | ||
| ``` | ||
|
|
||
| Returns **422 Unprocessable Entity** if a plugin with that name is already loaded. | ||
|
|
||
| ### Unload a plugin | ||
|
|
||
| ``` | ||
| DELETE /{network}/slipstream/plugins/{name} | ||
| ``` | ||
|
|
||
| Response (200): | ||
| ```json | ||
| { "unloaded": true } | ||
| ``` | ||
|
|
||
| Returns **404 Not Found** if no plugin with that name is loaded. | ||
|
|
||
| ### Reload a plugin (not yet implemented) | ||
|
|
||
| `PUT /{network}/slipstream/plugins/{name}` is not currently available. To update a plugin's | ||
| config during runtime, unload it with DELETE and reload it with POST. Otherwise, stop the snarkos service, update the config, and restart it, pointing at the new config. | ||
|
|
||
| --- | ||
|
|
||
| ## Example: curl Commands | ||
|
|
||
| ```bash | ||
| JWT="<your-jwt-token>" | ||
| BASE="http://localhost:3030/mainnet" | ||
|
|
||
| # List | ||
| curl -H "Authorization: Bearer $JWT" "$BASE/slipstream/plugins" | ||
|
|
||
| # Load | ||
| curl -X POST -H "Authorization: Bearer $JWT" \ | ||
| -H "Content-Type: application/json" \ | ||
| -d '{"config_file":"/path/to/plugin.json5"}' \ | ||
| "$BASE/slipstream/plugins" | ||
|
|
||
| # Unload | ||
| curl -X DELETE -H "Authorization: Bearer $JWT" \ | ||
| "$BASE/slipstream/plugins/postgres" | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Notes | ||
|
|
||
| - Plugins are loaded in startup order and unloaded in reverse order on shutdown. | ||
| - The `on_unload` method is called on every plugin during graceful shutdown. | ||
| - Plugin errors during `notify_mapping_update` / `notify_staking_reward` are logged as warnings | ||
| and never propagated to the node — a misbehaving plugin cannot crash the node. | ||
| - The plugin manager uses a `std::sync::RwLock`; `notify_*` calls acquire a read lock, while | ||
| load/unload/reload operations acquire the write lock. Avoid long-running operations inside | ||
| plugin callbacks. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a better place to put this file rather than creating this new docs dir? (Unlike snarkVM there isn't a specific plugins crate to put this in)