Crates.io | solana-geyser-plugin-scaffold |
lib.rs | solana-geyser-plugin-scaffold |
version | 1.11.2 |
source | src |
created_at | 2022-09-24 08:56:11.182339 |
updated_at | 2022-09-27 17:07:18.210168 |
description | The simplest Solana Geyser Plugin ever |
homepage | |
repository | https://github.com/mwrites/solana-geyser-plugin-scaffold |
max_upload_size | |
id | 672948 |
size | 26,102 |
A Solana Validator can "leak" accounts and transactions data outside the validator. This flow of data is achieved through the The Geyser Plugin Interface.
An external library can plug into that interface by implementing the necessary functions and thus listen for accounts and transactions streams.
That dynamic library is provided to the validator at runtime. The validator can then open that library and call the implemented callbacks or hooks with accounts and transactions data.
The library can then feed on these data and take further actions, such as logging, inserting the data into a DB or a consumer/producer system, etc.
This is the simplest geyser plugin implementation you will encounter, all it does is log every calls from the plugin manager to our plugin scaffold. This is a good start to familiarize yourself with the plugin workflow, and most importantly debug.
⚠️ The code is for educational purpose, in a production setting, you would want to remove any fancy logs and do the minimum work possible in the hooks by leveraging threads, different process or external services, etc...
Run:
./scripts/run.sh
How do I know if it works?
./scripts/logs.sh
Plugin or validator crashing?
./scripts/check_errors.sh
The dynamic library path is provided to the validator using the --geyser-plugin-config
parameter.
For example when using the test validator:
solana-test-validator --geyser-plugin-config config/geyser-plugin-config-mac.json
# or use ./scripts/run.sh
At a minimum the config file should:
For example:
{
"libpath": "libsolana_geyser_plugin_scaffold.dylib"
}
Of course your production validator won't run on mac, so update the path accordingly and use the .so version.
Additionally, at runtime the Solana Plugin Manager will pass back the path to that config file to your plugin. The config_file
path will be provided on the on_load(&mut self, config_file: &str) lifecycle event.
So you can add any additional config you think your plugin might need. And parse it when your plugin gets loaded.
The starter project might be simple, but the most important for you is to be able to debug and see the logs.
Indeed, if you can get the data through, what's next is really up to you. The question is what will you do of these data?
Moving forward, please make sure to do the minimum of work into the trait callbacks! And not just the callbacks, but any synchronous execution paths that originates from them.
Indeed your plugin is running part of the validator, and the validator is ...extremly busy! You need to make sure to return as quickly as possible from the callbacks and do the minimum of work. From there, there are multiple strategies:
You might need one of the above solution, or combine all of them. The answer lies into your needs, your own infrastructure, and your team size.
(Recommended way)
Using your IDE, add some breakpoints in your library, find the option to attach to the solana-test-validator
process, and you can now debug your library code! For example, that is how you do it in CLion.
The terminal way
It's a bit hardcore, but it can be helpful to debug on your production machine. (If your IDE allows remote debugging with reverse SSH tunneling, please go for it!)
Run the validator
Use lldb to attach to the process:
lldb -p `pgrep -x solana-test-validator`
At this point, the process has paused for you:
(lldb) Process XXXXX stopped
You can now set breakpoints in your library:
(lldb) breakpoint set --name update_account
(lldb) continue
Process 22436 resuming
thread #113, name = 'solPohTickProd', stop reason = breakpoint 1.1
frame #0: 0x000000010563ecd8 libsolana_geyser_plugin_scaffold.dylib`_$LT$solana_geyser_plugin_scaffold..geyser_plugin_hook..GeyserPluginHook$u20$as$u20$solana_geyser_plugin_interface..geyser_plugin_interface..GeyserPlugin$GT$::update_account::h6833f303509d44fe(self=0x0000000000000001, account=ReplicaAccountInfoVersions @ 0x00000002c4dc1c18, slot=16082, is_startup=false) at geyser_plugin_hook.rs:51:15