Add beacon chain update plugin and cranker executable#280
Add beacon chain update plugin and cranker executable#280brianjohnson5972 wants to merge 65 commits into
Conversation
…nsaction from running indefinitely and using wait_for before calling get to allow for timeout.
There was a problem hiding this comment.
Pull request overview
This PR adds new infrastructure for periodically fetching Ethereum beacon-chain metrics and pushing them on-chain, plus a lightweight runner executable to operate those updates without a full node.
Changes:
- Introduces
beacon_chain_update_pluginto fetch queue/APY data from beaconcha.in and submit contract updates via the outpost Ethereum client. - Adds
crankeras a standalone executable that initializes only the plugin subset required for beacon-chain updates. - Adds a cron expression parser to
cron_pluginand updates libfc Ethereum/JSON utilities (tx block identification + big-integer JSON parsing fixes).
Reviewed changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| programs/cranker/src/main.cpp | New minimal entrypoint that boots only the plugins required for beacon-chain updates. |
| programs/cranker/README.md | Documents cranker usage and CLI configuration. |
| programs/cranker/CMakeLists.txt | Adds build target for the cranker executable. |
| programs/CMakeLists.txt | Adds cranker subdirectory to the programs build. |
| plugins/outpost_ethereum_client_plugin/src/outpost_ethereum_client_plugin.cpp | Updates client parsing and makes getters const. |
| plugins/outpost_ethereum_client_plugin/include/sysio/outpost_ethereum_client_plugin.hpp | Makes client/ABI getters const. |
| plugins/cron_plugin/test/test_cron_parser.cpp | Adds unit tests for cron expression parsing behavior. |
| plugins/cron_plugin/src/services/cron_parser.cpp | Implements cron string parsing into cron_service::job_schedule. |
| plugins/cron_plugin/include/sysio/services/cron_parser.hpp | Exposes cron parser API. |
| plugins/cron_plugin/CRON_PARSER_USAGE.md | Usage documentation for the new cron parser. |
| plugins/CMakeLists.txt | Adds beacon chain update plugin to the plugins build. |
| plugins/beacon_chain_update_plugin/test/test_beacon_chain_update_plugin.cpp | Adds unit tests for beacon-chain update parsing utilities. |
| plugins/beacon_chain_update_plugin/test/main.cpp | Boost.Test entrypoint for beacon-chain update plugin tests. |
| plugins/beacon_chain_update_plugin/test/CMakeLists.txt | Builds and registers the beacon-chain update plugin test binary. |
| plugins/beacon_chain_update_plugin/src/beacon_chain_update_plugin.cpp | Implements the plugin: scheduling, HTTP fetch, contract tx submission, and parsing helpers. |
| plugins/beacon_chain_update_plugin/include/sysio/beacon_chain_update_plugin.hpp | Declares the beacon chain update plugin. |
| plugins/beacon_chain_update_plugin/include/sysio/beacon_chain_update_detail.hpp | Declares testable parsing/utility helpers (queue length, APY conversion). |
| plugins/beacon_chain_update_plugin/CMakeLists.txt | Builds the new plugin and links required dependencies (cron/outpost/curl). |
| libraries/libfc/src/network/ethereum/ethereum_client.cpp | Fixes call/tx hex prefixing and adds identify_block_for_transaction. |
| libraries/libfc/include/fc/network/ethereum/ethereum_client.hpp | Declares the new identify_block_for_transaction API. |
| libraries/libfc/src/network/ethereum/ethereum_abi.cpp | Adjusts ABI decoding to tolerate missing name (e.g., receive/constructor). |
| libraries/libfc/include/fc/network/ethereum/ethereum_abi.hpp | Adds receive to ABI invoke target type enum/reflection. |
| libraries/libfc/src/io/json.cpp | Fixes numeric routing boundaries for big integers when parsing JSON. |
| CRON_PARSER_SUMMARY.md | High-level documentation summary of the cron parser addition. |
| cmake/chain-tools.cmake | Adds beacon_chain_update_plugin to the default chain_target() link set. |
Comments suppressed due to low confidence (2)
plugins/outpost_ethereum_client_plugin/src/outpost_ethereum_client_plugin.cpp:94
chain_idis now always passed as a value (default-constructed to 0) even when the spec omits the optional chain id. This changes behavior vs the previousstd::optionalapproach and can cause transactions to be signed with chainId=0. Consider keepingstd::optional<fc::uint256> chain_idand only setting it whenparts.size() == 4(otherwise passstd::nulloptintoethereum_client).
fc::uint256 chain_id;
fc::ostring chain_id_str;
if (parts.size() == 4) {
chain_id_str = parts[3];
if (chain_id_str.has_value())
chain_id = fc::to_uint256(chain_id_str.value());
} else {
ilog("chainId: none");
}
auto sig_provider = plug_sig->get_provider(sig_id);
my->add_client(id,
std::make_shared<ethereum_client_entry_t>(
id,
url,
sig_provider,
std::make_shared<ethereum_client>(sig_provider, url,
chain_id)));
cmake/chain-tools.cmake:33
- Adding
beacon_chain_update_pluginto the globalchain_target()link list will pull this plugin (and its dependencies like libcurl/OpenSSL) into every executable that useschain_target(including unrelated programs/tests). If onlycrankerneeds this plugin, prefer linking it only to that target instead of the global list.
prometheus_plugin
resource_monitor_plugin
state_history_plugin
signature_provider_manager_plugin
outpost_client_plugin
outpost_ethereum_client_plugin
outpost_solana_client_plugin
beacon_chain_update_plugin
test_control_api_plugin
test_control_plugin
trace_api_plugin
chain_plugin
appbase
${PLUGIN_DEFAULT_DEPENDENCIES}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| file(GLOB_RECURSE SRC_FILES src/*.cpp src/*.hpp) | ||
|
|
||
| chain_target(${TARGET_NAME} SOURCE_FILES ${SRC_FILES}) |
There was a problem hiding this comment.
cranker is intended to be lightweight, but using chain_target() will link in the full default plugin set from cmake/chain-tools.cmake (net, producer, state_history, etc.), increasing binary size and dependencies. Consider creating a minimal executable target (add_executable + target_link_libraries) that links only the required libraries/plugins for cranker.
There was a problem hiding this comment.
Removed beacon_chain_update_plugin from chain-tools.cmake, but leaving chain_target
| parse_components(vo.inputs, "inputs"); | ||
| parse_components(vo.outputs, "outputs"); | ||
| bool missed = true; | ||
| if(deferred_name) { |
There was a problem hiding this comment.
I had initially put this in for reporting what we don't expect to see, and determine if something else needs to be reported. Not sure if we should drop or at least keep it in here while we are still working on ethereum client scripts
There was a problem hiding this comment.
changed to throwing exception to identify what we may be missing.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
heifner
left a comment
There was a problem hiding this comment.
Code review of cranker/beacon_chain_update_plugin changes. 16 findings across 5 files.
jglanz
left a comment
There was a problem hiding this comment.
plus all the other stuff we just discussed
| * thread that polls eth_getTransactionReceipt until the receipt is available. | ||
| * @throws fc::network::json_rpc::json_rpc_exception if the initial RPC call fails. | ||
| */ | ||
| std::future<uint64_t> identify_block_for_transaction(const std::string& tx_hash); |
There was a problem hiding this comment.
template <typename Fn, typename ... Args>
std::expected<decltype(Fn(Args...)), fc::exception> retry(retry_config_t config, Fn fn, Args&& ...) { ... }
jglanz
left a comment
There was a problem hiding this comment.
I took 2 secs to look and saw some glaring issues. Remove the curl dep - rebase on to feature/opp-part2 - this should have near 0 impact - remove changes from sig prov plugin, etc. the 2 modifications to existing code that we discussed was adding receive and enhancing the cron parsing, but i even question the need for that
- curl should not be a dep for
fc,i know its used for clio, but thats legacy
…nto `wire-sysio` removing a potential circular dep with `wire-libraries-ts` ## Overview Moved `protoc-gen-<solana|solidity>` plugins and protobuf-bundler into `wire-sysio` removing a potential circular dep with `wire-libraries-ts` Additionally, it adds a build options `BUILD_OPP_BUNDLES` (default is `ON`), which allows gating of the OPP bundler The output by default is `<wire-sysio>/build/opp/<solidity|typescript|solana>` and can be link with either `pnpm` or `npm` package managers from there in the case you'd like to use them for local development.
…lock and other needed changes
|
@jglanz here is the description of all the changes to existing files: cmake/dependencies.boost.cmakeAdding url to boost dependencies for http api support libraries/custom_appbase/include/sysio/chain/app.hppPreventing the app plumbing from revealing the api key. libraries/libfc/network/ethereum/ethereum_abi.cppAdded libraries/libfc/network/ethereum/ethereum_client.cppAdded method get_block_for_transaction as a helper function to retrieve the transaction receipt, if it exists, and return the block number that the transaction is part of. libraries/libfc/src/io/json.cppThe json processing is (incorrectly) dropping the fact that integer values that are wrapped by quotes, were originally quoted, and is processed just as a bare integer. Fixing this caused a ripple effect in many unit tests and determined that providing support for integers greater than int64 as in256 would be the solution at this time and writing up a Jira task to deal with the complete fix when we are past the critical timeline. Also added returning a variant variable on all paths in that method to ensure ellision is allowed. plugins/cron_plugin/include/sysio/services/cron_service.hppAdded blocking_retry plugins/cron_plugin/src/services/cron_parser.cppAdded support for cron schedule format: "* * * * " (and claude through in a millisecond version: " * * * * *") to allow configuring a cron schedule for a job taking advantage of the expansive interface for the cron_service. plugins/outpost_ethereum_client_plugin/src/outpost_ethereum_client_plugin.cppChange three existing implicitly const methods to have the explicit "const" so they could be called using a const&. |
The compiled .wasm/.abi artifacts under contracts/ were modified on this branch as a build byproduct. Restore them to the origin/master versions so this branch carries no contract diff into the master merge. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| */ | ||
| void wire_eth_maintenance_plugin::interrupt() { | ||
| ilog("interrupt"); | ||
| app().executor().stop(); |
There was a problem hiding this comment.
This is done for you by custom_appbase. No need to call it here.
| wire_eth_maintenance_plugin& wire_plug = app().get_plugin<wire_eth_maintenance_plugin>(); | ||
| exe.set_stop_executor_cb([&wire_plug]() { | ||
| ilog("Exiting cranker"); | ||
| wire_plug.interrupt(); |
There was a problem hiding this comment.
Not needed as wire_plug.interrupt() only does what the default does anyway.
| for(const auto& client_spec : client_specs) { | ||
| ilog("found beacon chain outpost addresses: {}", client_spec); | ||
| fc::variant addrs = fc::json::from_file<fc::variant>(client_spec); | ||
| const auto addrs_obj = addrs.get_object(); |
Summary
contracts.
What the plugin does
beacon_chain_update_plugin runs on a configurable cron schedule and:
with the estimated wait time in seconds.
All on-chain calls are submitted via the existing outpost_ethereum_client_plugin. Block confirmation is awaited using a new identify_block_for_transaction future.
Configuration options (all via nodeop config):
Changes by area
plugins/beacon_chain_update_plugin/ (new)
plugins/beacon_chain_update_plugin/test/ (new)
epsilon robustness).
programs/cranker/ (new)
plugins/cron_plugin/ (new files)
libraries/libfc/src/network/ethereum/ethereum_client.cpp
(10 min); captures weak_from_this() to prevent use-after-free if the client is destroyed before the transaction mines.
libraries/libfc/src/io/json.cpp
numbers ≥ 922... to fall through to int128, 20-digit unsigned values to be routed to uint256 instead of uint128, and the int256/uint256 overflow checks to use inverted direction
comparisons. All four boundaries and their comparison operators are corrected.