Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
76654be
Initial Crank: Error including cron_plugin
brianjohnson5972 Mar 2, 2026
429c899
Initial Crank: Needed changes for client
brianjohnson5972 Mar 20, 2026
f2ac82c
Initial Crank: Adding DepositManager and WithdrawalQueue contracts
brianjohnson5972 Mar 20, 2026
dff465d
Initial Crank: Working
brianjohnson5972 Mar 25, 2026
0fc09cc
Initial Crank: Fixed last errors
brianjohnson5972 Mar 30, 2026
04f8348
Initial Crank: Simplified code
brianjohnson5972 Mar 31, 2026
0402d22
Initial Crank: Added unit tests
brianjohnson5972 Mar 31, 2026
92bb896
Initial Crank: Fix to prevent ethereum_client::identify_block_for_tra…
brianjohnson5972 Apr 2, 2026
e1c9aa3
Initial Crank: Fixed issue with http::read blocking indefinitely.
brianjohnson5972 Apr 2, 2026
24d6374
Initial Crank: Added initialization for curl.
brianjohnson5972 Apr 2, 2026
09cd13c
Initial Crank: Fixed tracking default schedule and updated README.md.
brianjohnson5972 Apr 2, 2026
8f20ec5
Apply suggestions from code review
brianjohnson5972 Apr 2, 2026
b56d806
Initial Crank: Fixed remaining PR comments from Kevin.
brianjohnson5972 Apr 10, 2026
f92c2c6
Initial Crank: Fixed remaining PR comments from Kevin and Jonathan.
brianjohnson5972 Apr 13, 2026
d8b7d9e
Initial Crank: Refactored retry logic into cron_service to prevent de…
brianjohnson5972 Apr 13, 2026
8907468
Initial Crank: Added caching the last nonce to ensure that the client…
brianjohnson5972 Apr 15, 2026
70612d2
Initial Crank: Changed retry method to blocking_retry for clearity.
brianjohnson5972 Apr 15, 2026
7ddd427
Initial Crank: Refactoring of beacon_chain_update_plugin and other ch…
brianjohnson5972 Apr 17, 2026
92634ce
Initial Crank: Renaming of beacon_chain_update_plugin and other PR ch…
brianjohnson5972 Apr 17, 2026
3d10584
Initial Crank: Simplifying support for json exceeding 64 bit integers…
brianjohnson5972 Apr 17, 2026
1624347
Initial Crank: Fixed PR comments from Kevin
brianjohnson5972 Apr 17, 2026
4816e6d
Initial Crank: Fixed PR comments from Chuy
brianjohnson5972 Apr 20, 2026
351a94a
Initial Crank: Minor Cleanup
brianjohnson5972 Apr 20, 2026
6f11d07
Initial Crank: Cleanups found by Claude
brianjohnson5972 Apr 20, 2026
5699d75
Initial Crank: Final cleanup by Claude
brianjohnson5972 Apr 20, 2026
8804659
Merge remote-tracking branch 'origin/master' into feature/crank_queue…
brianjohnson5972 Apr 21, 2026
69a0a96
Initial Crank: Fixing merge from master error
brianjohnson5972 Apr 21, 2026
a3e44e4
Initial Crank: Making json integer conversion simpler and more effici…
brianjohnson5972 Apr 21, 2026
2df59b1
Initial Crank: Last comment fixes
brianjohnson5972 Apr 21, 2026
18efd89
Initial Crank: Cleanup of cron_parser::split
brianjohnson5972 Apr 21, 2026
cbb1cf4
Initial Crank: Added handling for Interrupt signal handling for clean…
brianjohnson5972 Apr 22, 2026
723c19a
Initial Crank: Reverted code that wasn't meant to be committed
brianjohnson5972 Apr 22, 2026
9580154
Initial Crank: Remaining heifner PR comment fixes
brianjohnson5972 Apr 27, 2026
18603cb
Initial Crank: Missed code to remove.
brianjohnson5972 Apr 27, 2026
ec2429c
Initial Crank: Optimized u/int64 conversion path
brianjohnson5972 Apr 27, 2026
12dceb5
Initial Crank: actual remaining heifner PR comment fixes
brianjohnson5972 Apr 27, 2026
a4f1a71
chain_plugin: run read_table_rows inline when called from main thread
heifner Apr 27, 2026
1bf51df
# Achieved memory & on-chain storage stability (`>2400` epochs over `…
jglanz Apr 27, 2026
abe0a31
Initial Crank: final heifner PR comment fixes
brianjohnson5972 Apr 28, 2026
7ec6547
Initial Crank: cleanup
brianjohnson5972 Apr 28, 2026
44a5135
Initial Crank: Reverting change for signature provider plugin
brianjohnson5972 Apr 28, 2026
45882f6
Moved `file:line` to the end of `line-format` for readability in lnav.
jglanz Apr 28, 2026
7a32fe1
# Moved `protoc-gen-<solana|solidity>` plugins and protobuf-bundler i…
jglanz Apr 28, 2026
2bcb00b
Initial Crank: Get rid of Curl
brianjohnson5972 Apr 28, 2026
736dc1d
Initial Crank: Removing curl_init.*
brianjohnson5972 Apr 28, 2026
f08351c
Initial Crank: Missed committing reverting of cmake change
brianjohnson5972 Apr 29, 2026
8b86db2
Initial Crank: Removed non-necessary code changes
brianjohnson5972 Apr 30, 2026
4e3efa0
Initial Crank: Missed removing two code changes
brianjohnson5972 Apr 30, 2026
3a5eabf
Initial Crank: Adding back in waiting on transaction making it in a b…
brianjohnson5972 Apr 30, 2026
87e418c
Updated OPP generate bundles script
jglanz Apr 30, 2026
7b22e17
Updated OPP generate bundles script
jglanz Apr 30, 2026
bc58ab1
Updated OPP generate bundles script
jglanz Apr 30, 2026
b3a4bd3
Updated OPP generate bundles script
jglanz Apr 30, 2026
8813d87
Initial Crank: Removing unintended change
brianjohnson5972 Apr 30, 2026
1acf232
Initial Crank: Adding back in intended ellision variant variable return
brianjohnson5972 Apr 30, 2026
36cca89
Initial Crank: Cleanup includes
brianjohnson5972 Apr 30, 2026
d743f96
Removed weird leftover dep `z`
jglanz May 4, 2026
63e9910
Removed weird leftover dep `z` - updated lockfile
jglanz May 4, 2026
99ea74f
Initial Crank: Removed unneeded change
brianjohnson5972 May 4, 2026
dbf4fac
Initial Crank: Removed unneeded change and improved exception handling
brianjohnson5972 May 4, 2026
996a817
Initial Crank: Removing change to number of threads.
brianjohnson5972 May 4, 2026
f4c232a
Merge remote-tracking branch 'origin/feature/opp-part2' into feature/…
brianjohnson5972 May 5, 2026
0ba6177
Initial Crank: Merged in branch retry implementation.
brianjohnson5972 May 6, 2026
5711f75
Merge remote-tracking branch 'origin/master' into feature/crank_queue…
brianjohnson5972 May 21, 2026
7dd0e3b
revert: restore contracts artifacts to origin/master
brianjohnson5972 May 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmake/dependencies.boost.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ set(BOOST_COMPONENTS
system
thread
unit_test_framework
url
)
foreach (COMPONENT ${BOOST_COMPONENTS})
find_package(boost_${COMPONENT} ${BOOST_VERSION} EXACT CONFIG REQUIRED)
Expand Down
3 changes: 2 additions & 1 deletion libraries/custom_appbase/include/sysio/chain/app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ void log_non_default_options(const std::vector<bpo::basic_option<char>>& options
for (const auto& op : options) {
bool mask = false;
if (op.string_key == "peer-private-key"s
|| op.string_key == "p2p-auto-bp-peer"s) {
|| op.string_key == "p2p-auto-bp-peer"s
|| op.string_key == "beacon-chain-api-key"s) {
mask = true;
}
std::string v;
Expand Down
7 changes: 4 additions & 3 deletions libraries/libfc/include/fc/network/ethereum/ethereum_abi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
namespace fc::network::ethereum {

namespace abi {
enum class invoke_target_type { function, constructor, event, error };
enum class invoke_target_type { function, constructor, event, error, receive };

enum class data_type : int64_t {
boolean,
Expand Down Expand Up @@ -196,7 +196,8 @@ using contract_invoke_data_items = std::vector<contract_invoke_data>;
* Encode a contract call
* @return hex string of encoded call `data` field in RLP format
*/
std::string contract_encode_data(const abi::contract& contract, const contract_invoke_data_items& params);
std::string contract_encode_data(const abi::contract& contract, const contract_invoke_data_items& params,
bool add_hex_prefix = false);

template <typename T>
concept not_abi_data_params_t = !std::is_same_v<std::decay_t<T>, contract_invoke_data_items>;
Expand Down Expand Up @@ -297,7 +298,7 @@ struct get_typename<fc::network::ethereum::abi::data_type> {
};
}; // namespace fc

FC_REFLECT_ENUM(fc::network::ethereum::abi::invoke_target_type, (function)(constructor)(event)(error));
FC_REFLECT_ENUM(fc::network::ethereum::abi::invoke_target_type, (function)(constructor)(event)(error)(receive));

FC_REFLECT(fc::network::ethereum::abi::component_type::list_config_type, (is_list)(size));
FC_REFLECT(fc::network::ethereum::abi::component_type, (name)(type)(list_config)(components)(internal_type));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,13 @@ class ethereum_client : public std::enable_shared_from_this<ethereum_client> {
*/
std::string send_raw_transaction(const std::string& raw_tx_data);

/**
* @brief Retrieves the transaction receipt and extracts the block number.
* @param tx_hash The transaction hash
* @return The block number if the receipt is available, or std::nullopt if not yet mined
*/
std::optional<uint64_t> get_block_for_transaction(const std::string& tx_hash);

/**
* @brief Submit a raw transaction and await inclusion + N confirmations.
*
Expand Down
97 changes: 88 additions & 9 deletions libraries/libfc/src/io/json.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <fc/io/json.hpp>
//#include <fc/io/fstream.hpp>
//#include <fc/io/sstream.hpp>
#include <fc/int128.hpp>
#include <fc/int256.hpp>
#include <fc/log/logger.hpp>
//#include <utfcpp/utf8.h>
#include <fc/utf8.hpp>
Expand Down Expand Up @@ -28,6 +30,19 @@ namespace fc

#include <fc/io/json_relaxed.hpp>

namespace
{

// Max |value| decimal strings used to pick the smallest variant bucket that fits a token.
// Signed entries use the magnitude of *_MIN (one greater than *_MAX); unsigned entries use *_MAX.
constexpr std::string_view int64_max_magnitude_str = "9223372036854775808"; // | INT64_MIN|
constexpr std::string_view uint64_max_magnitude_str = "18446744073709551615"; // |UINT64_MIN|
constexpr std::string_view int256_max_str =
"57896044618658097711785492504343953926634992332820282019728792003956564819968";
constexpr std::string_view uint256_max_str =
"115792089237316195423570985008687907853269984665640564039457584007913129639935";
}

Comment thread
heifner marked this conversation as resolved.
namespace fc
{
namespace {
Expand Down Expand Up @@ -307,6 +322,7 @@ namespace fc
s += in.get();
}
bool done = false;
variant ret;

try
{
Expand Down Expand Up @@ -337,7 +353,8 @@ namespace fc
if( isalnum( c ) )
{
s += string_from_token( in );
return s;
ret = std::move(s);
return ret;
}
done = true;
break;
Expand All @@ -350,14 +367,76 @@ namespace fc
catch (const std::ios_base::failure&)
{
}
const std::string& str = s;
if (str == "-." || str == "." || str == "-") // check the obviously wrong things we could have encountered
FC_THROW_EXCEPTION(parse_error_exception, "Can't parse token \"{}\" as a JSON numeric constant", str);
if( dot )
return parser_type == json::parse_type::legacy_parser_with_string_doubles ? variant(str) : variant(to_double(str));
if( neg )
return to_int64(str);
return to_uint64(str);

const auto no_neg_start = neg ? 1 : 0;
const auto start = s.find_first_not_of('0', no_neg_start);
const auto str = (start != std::string::npos)
? std::string_view(s).substr(start)
: std::string_view{};

// if the string is empty and we had actual digits after the sign
if (str.empty() && s.size() > no_neg_start) {
ret = 0u;
return ret;
}

// check for s== ".", "-","-.", since "[-]0*" is checked above
if (str == "." || str.empty()) // check the obviously wrong things we could have encountered
Comment thread
brianjohnson5972 marked this conversation as resolved.
FC_THROW_EXCEPTION(parse_error_exception, "Can't parse token \"{}\" as a JSON numeric constant", str);
Comment thread
heifner marked this conversation as resolved.

if( dot ) {
ret = parser_type == json::parse_type::legacy_parser_with_string_doubles
? variant(std::move(s))
: variant(to_double(s));
return ret;
}

if( neg ) {
// Common case: fits in int64
if (str.length() < int64_max_magnitude_str.length() ||
(str.length() == int64_max_magnitude_str.length() && str <= int64_max_magnitude_str)) {
ret = to_int64(s);
return ret;
}

if (str.length() > int256_max_str.length() ||
(str.length() == int256_max_str.length() && str > int256_max_str)) {
FC_THROW_EXCEPTION(parse_error_exception,
"Negative numeric token \"{}\" exceeds int256 range", s);
}

if (str == int256_max_str) {
const auto val = std::numeric_limits<fc::int256>::min();
ret = val;
return ret;
}

// using the string with no leading 0s, to avoid the string being assumed to be in octal,
// since a leading 0 with only digits between 0 and 7 are assumed to be octal
fc::int256 val256(str);
val256 = -val256;
ret = std::move(val256);
return ret;
}

// Common case: fits in uint64
if (str.length() < uint64_max_magnitude_str.length() ||
(str.length() == uint64_max_magnitude_str.length() && str <= uint64_max_magnitude_str)) {
ret = to_uint64(s);
return ret;
}

if (str.length() > uint256_max_str.length() ||
(str.length() == uint256_max_str.length() && str > uint256_max_str)) {
FC_THROW_EXCEPTION(parse_error_exception,
"Numeric token \"{}\" exceeds uint256 range", s);
}

// using the string with no leading 0s, to avoid the string being assumed to be in octal,
// since a leading 0 with only digits between 0 and 7 are assumed to be octal
fc::uint256 val256(str);
ret = std::move(val256);
return ret;
}

template<typename T>
Expand Down
18 changes: 15 additions & 3 deletions libraries/libfc/src/network/ethereum/ethereum_abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,8 @@ abi::contract abi::parse_contract(const fc::variant& v) {
* @return Hex string of encoded call data (selector + encoded parameters)
* @throws fc::exception if parameter count mismatches or encoding fails
*/
std::string contract_encode_data(const abi::contract& contract, const std::vector<fc::variant>& params) {
std::string contract_encode_data(const abi::contract& contract, const std::vector<fc::variant>& params,
bool add_hex_prefix) {
const auto& inputs = contract.inputs;
FC_ASSERT_FMT(inputs.size() == params.size(), "Parameter count mismatch (expected={}, provided={})", inputs.size(),
params.size());
Expand Down Expand Up @@ -890,7 +891,7 @@ std::string contract_encode_data(const abi::contract& contract, const std::vecto
out.insert(out.end(), tail.begin(), tail.end());
}

return fc::to_hex(out);
return fc::to_hex(out, add_hex_prefix);
}


Expand Down Expand Up @@ -1058,7 +1059,12 @@ void fc::from_variant(const fc::variant& var, fc::network::ethereum::abi::contra

FC_ASSERT(var.is_object(), "Variant must be an object to deserialize ABI contract");
auto& obj = var.get_object();
vo.name = obj["name"].as_string();
const auto name_itr = obj.find("name");
const bool no_name = name_itr == obj.end();
if (!no_name) {
vo.name = name_itr->value().as_string();
}

auto type_str = obj["type"].as_string();
vo.type = fc::reflector<fc::network::ethereum::abi::invoke_target_type>::from_string(type_str.c_str());

Expand All @@ -1079,4 +1085,10 @@ void fc::from_variant(const fc::variant& var, fc::network::ethereum::abi::contra

parse_components(vo.inputs, "inputs");
parse_components(vo.outputs, "outputs");
if(no_name) {
// we expect ABI contracts that have the legacy payment ethereum interface
const bool valid = type_str == "receive" &&
obj["stateMutability"].as_string() == "payable";
FC_ASSERT(valid, "Variant Object must have a `name` key to deserialize ABI contract");
}
}
14 changes: 12 additions & 2 deletions libraries/libfc/src/network/ethereum/ethereum_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ fc::variant ethereum_client::execute(const std::string& method, const fc::varian
fc::variant ethereum_client::execute_contract_view_fn(const address& contract_address, const abi::contract& abi,
const std::string& block_tag,
const contract_invoke_data_items& params) {
auto abi_call_encoded = contract_encode_data(abi, params);
auto abi_call_encoded = contract_encode_data(abi, params, true);
auto to_data_mvo = fc::mutable_variant_object("to", to_hex(contract_address, true))("data", abi_call_encoded);
fc::variants rpc_params = {to_data_mvo, fc::variant(block_tag)};
return execute("eth_call", rpc_params);
Expand Down Expand Up @@ -120,7 +120,7 @@ fc::variant ethereum_client::execute_contract_tx_fn(const eip1559_tx& source_tx,
tx_encoded = rlp::encode_eip1559_signed_typed(tx);
}

return send_raw_transaction(to_hex(tx_encoded));
return send_raw_transaction(to_hex(tx_encoded, true));
}


Expand Down Expand Up @@ -478,6 +478,16 @@ std::string ethereum_client::send_raw_transaction(const std::string& raw_tx_data
return resp.as_string();
}

std::optional<uint64_t> ethereum_client::get_block_for_transaction(const std::string& tx_hash) {
auto receipt = get_transaction_receipt(tx_hash);
if (receipt.is_null())
return std::nullopt;
const auto& obj = receipt.get_object();
if (!obj.contains("blockNumber") || obj["blockNumber"].is_null())
return std::nullopt;
return static_cast<uint64_t>(to_uint256(obj["blockNumber"]));
}

std::string ethereum_client::wait_for_confirmation(const std::string& tx_hash,
const ethereum_confirm_options& opts) {
// Phase 1: wait for the receipt to exist. A null result means the tx
Expand Down
Loading