forked from paradigmxyz/reth
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Creating telos-reth binary which uses TelosNode from the telos crate
- Loading branch information
Showing
12 changed files
with
928 additions
and
52 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains 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 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 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 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,50 @@ | ||
#![allow(missing_docs)] | ||
|
||
use std::sync::Arc; | ||
use clap::Parser; | ||
use reth::cli::Cli; | ||
use reth_node_telos::TelosArgs; | ||
use reth_node_telos::TelosNode; | ||
use reth_telos_rpc::TelosClient; | ||
|
||
// We use jemalloc for performance reasons. | ||
#[cfg(all(feature = "jemalloc", unix))] | ||
#[global_allocator] | ||
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; | ||
|
||
#[cfg(all(feature = "optimism", not(test)))] | ||
compile_error!("Cannot build the `telos-reth` binary with the `optimism` feature flag enabled. Did you mean to build `op-reth`?"); | ||
|
||
#[cfg(feature = "telos")] | ||
fn main() { | ||
use reth::cli::Cli; | ||
|
||
reth_cli_util::sigsegv_handler::install(); | ||
|
||
// Enable backtraces unless a RUST_BACKTRACE value has already been explicitly provided. | ||
if std::env::var_os("RUST_BACKTRACE").is_none() { | ||
std::env::set_var("RUST_BACKTRACE", "1"); | ||
} | ||
|
||
if let Err(err) = Cli::<TelosArgs>::parse().run(|builder, telos_args| async move { | ||
let handle = builder | ||
.node(TelosNode::new(telos_args.clone())) | ||
.extend_rpc_modules(move |ctx| { | ||
// register sequencer tx forwarder | ||
if telos_args.telos_endpoint.is_some() { | ||
ctx.registry.set_eth_raw_transaction_forwarder(Arc::new(TelosClient::new( | ||
telos_args, | ||
))); | ||
} | ||
|
||
Ok(()) | ||
}) | ||
.launch() | ||
.await?; | ||
|
||
handle.node_exit_future.await | ||
}) { | ||
eprintln!("Error: {err:?}"); | ||
std::process::exit(1); | ||
} | ||
} |
This file contains 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,36 @@ | ||
[package] | ||
name = "reth-node-telos" | ||
version.workspace = true | ||
edition.workspace = true | ||
rust-version.workspace = true | ||
license.workspace = true | ||
homepage.workspace = true | ||
repository.workspace = true | ||
|
||
[lints] | ||
workspace = true | ||
|
||
[dependencies] | ||
antelope-client.workspace = true | ||
reth-primitives.workspace = true | ||
|
||
reth-auto-seal-consensus.workspace = true | ||
reth-basic-payload-builder.workspace = true | ||
reth-beacon-consensus.workspace = true | ||
reth-ethereum-engine-primitives.workspace = true | ||
reth-evm-ethereum.workspace = true | ||
reth-network.workspace = true | ||
reth-node-api.workspace = true | ||
reth-node-builder.workspace = true | ||
reth-node-ethereum.workspace = true | ||
reth-payload-builder.workspace = true | ||
reth-provider.workspace = true | ||
reth-rpc.workspace = true | ||
reth-tracing.workspace = true | ||
reth-transaction-pool.workspace = true | ||
|
||
clap.workspace = true | ||
serde = { workspace = true, features = ["derive"] } | ||
|
||
[features] | ||
telos = [] |
This file contains 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,47 @@ | ||
//! clap [Args](clap::Args) for telos configuration | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Debug, Clone, Default, PartialEq, Eq, clap::Args)] | ||
#[clap(next_help_heading = "Telos")] | ||
pub struct TelosArgs { | ||
/// TelosZero endpoint to use for API calls (send_transaction, get gas price from table) | ||
#[arg(long = "telos.telos_endpoint", value_name = "HTTP_URL")] | ||
pub telos_endpoint: Option<String>, | ||
|
||
/// Signer account name | ||
#[arg(long = "telos.signer_account")] | ||
pub signer_account: Option<String>, | ||
|
||
/// Signer permission name | ||
#[arg(long = "telos.signer_permission")] | ||
pub signer_permission: Option<String>, | ||
|
||
/// Signer private key | ||
#[arg(long = "telos.signer_key")] | ||
pub signer_key: Option<String>, | ||
|
||
/// Seconds to cache gas price | ||
#[arg(long = "telos.gas_cache_seconds")] | ||
pub gas_cache_seconds: Option<u32>, | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use clap::{Args, Parser}; | ||
|
||
/// A helper type to parse Args more easily | ||
#[derive(Parser)] | ||
struct CommandParser<T: Args> { | ||
#[clap(flatten)] | ||
args: T, | ||
} | ||
|
||
#[test] | ||
fn test_parse_database_args() { | ||
let default_args = TelosArgs::default(); | ||
let args = CommandParser::<TelosArgs>::parse_from(["reth"]).args; | ||
assert_eq!(args, default_args); | ||
} | ||
} |
This file contains 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,166 @@ | ||
//! Standalone crate for Telos-specific Reth configuration and builder types. | ||
#![doc( | ||
html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", | ||
html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", | ||
issue_tracker_base_url = "https://github.com/telosnetwork/telos-reth/issues/" | ||
)] | ||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] | ||
|
||
#![cfg(feature = "telos")] | ||
|
||
use std::fmt::{Debug, Formatter}; | ||
use antelope::api::client::{APIClient, DefaultProvider}; | ||
use antelope::api::v1::structs::GetTableRowsParams; | ||
use antelope::chain::action::{Action, PermissionLevel}; | ||
use antelope::chain::checksum::{Checksum160, Checksum256}; | ||
use antelope::chain::name::Name; | ||
use antelope::chain::private_key::PrivateKey; | ||
use antelope::chain::transaction::{SignedTransaction, Transaction}; | ||
use antelope::serializer::{Decoder, Encoder, Packer}; | ||
use antelope::{name, StructPacker}; | ||
use reth_primitives::{TransactionSigned, U256}; | ||
use std::time::{Duration, Instant}; | ||
|
||
pub mod args; | ||
pub mod node; | ||
|
||
pub use crate::args::TelosArgs; | ||
pub use crate::node::TelosNode; | ||
|
||
|
||
/// Telos Network Config | ||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] | ||
#[derive(Debug, Clone, Default)] | ||
pub struct TelosNetworkConfig { | ||
pub api_client: APIClient<DefaultProvider>, | ||
pub signer_account: Name, | ||
pub signer_permission: Name, | ||
pub signer_key: PrivateKey, | ||
pub gas_cache: GasPriceCache, | ||
} | ||
|
||
#[derive(StructPacker)] | ||
pub struct RawActionData { | ||
pub ram_payer: Name, | ||
pub tx: Vec<u8>, | ||
pub estimate_gas: bool, | ||
pub sender: Option<Checksum160>, | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct GasPriceCache { | ||
api_client: Box<APIClient<DefaultProvider>>, | ||
gas_cache_duration: Duration, | ||
value: Option<(U256, Instant)>, | ||
} | ||
|
||
impl Debug for GasPriceCache { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "GasPriceCache duration: ") | ||
} | ||
} | ||
|
||
impl Default for GasPriceCache { | ||
fn default() -> Self { | ||
GasPriceCache { | ||
api_client: Box::new(APIClient::<DefaultProvider>::default_provider("https://example.com".into()).unwrap()), | ||
gas_cache_duration: Duration::default(), | ||
value: None | ||
} | ||
} | ||
} | ||
|
||
#[derive(StructPacker, Default)] | ||
struct TelosEVMConfig { | ||
trx_index: u32, | ||
last_block: u32, | ||
gas_used_block: Checksum256, | ||
gas_price: Checksum256, | ||
revision: Option<u32>, | ||
} | ||
|
||
impl GasPriceCache { | ||
pub fn new(api_client: Box<APIClient<DefaultProvider>>, gas_cache_duration: Duration) -> Self { | ||
GasPriceCache { api_client, gas_cache_duration, value: None } | ||
} | ||
|
||
async fn load_value(&self) -> U256 { | ||
let table_rows_params = GetTableRowsParams { | ||
code: name!("eosio.evm"), | ||
table: name!("config"), | ||
scope: Some(name!("eosio.evm")), | ||
lower_bound: None, | ||
upper_bound: None, | ||
limit: Some(1), | ||
reverse: None, | ||
index_position: None, | ||
show_payer: None, | ||
}; | ||
let config_result = | ||
self.api_client.v1_chain.get_table_rows::<TelosEVMConfig>(table_rows_params).await.unwrap(); | ||
|
||
return U256::from_be_slice(&config_result.rows[0].gas_price.data); | ||
} | ||
|
||
pub async fn get(&mut self) -> &U256 { | ||
let now = Instant::now(); | ||
if self.value.as_ref().map_or(true, |&(_, ref expiry)| *expiry <= now) { | ||
let new_val = self.load_value(); // Call the hardcoded loader function | ||
self.value = Some((new_val.await, now + self.gas_cache_duration)); | ||
} | ||
&self.value.as_ref().unwrap().0 | ||
} | ||
} | ||
|
||
pub async fn send_to_telos( | ||
network_config: &TelosNetworkConfig, | ||
trxs: &Vec<TransactionSigned>, | ||
) -> Result<String, String> { | ||
let get_info = network_config.api_client.v1_chain.get_info().await.unwrap(); | ||
let trx_header = get_info.get_transaction_header(90); | ||
let _trxs_results = trxs.iter().map(|trx| { | ||
let trx_header = trx_header.clone(); | ||
async move { | ||
let mut trx_bytes = Vec::new(); | ||
trx.encode_enveloped(&mut trx_bytes); | ||
|
||
let raw_action_data = RawActionData { | ||
ram_payer: name!("eosio.evm"), | ||
tx: trx_bytes, | ||
estimate_gas: false, | ||
sender: None, | ||
}; | ||
|
||
let action = Action::new_ex( | ||
name!("eosio.evm"), | ||
name!("raw"), | ||
vec![PermissionLevel::new( | ||
network_config.signer_account, | ||
network_config.signer_permission, | ||
)], | ||
raw_action_data, | ||
); | ||
|
||
let transaction = Transaction { | ||
header: trx_header, | ||
context_free_actions: vec![], | ||
actions: vec![action], | ||
extension: vec![], | ||
}; | ||
|
||
let signed_telos_transaction = SignedTransaction { | ||
transaction: transaction.clone(), | ||
signatures: vec![network_config | ||
.signer_key | ||
.sign_message(&transaction.signing_data(&get_info.chain_id.data.to_vec()))], | ||
context_free_data: vec![], | ||
}; | ||
|
||
let result = network_config.api_client.v1_chain.send_transaction(signed_telos_transaction); | ||
|
||
result.await.unwrap().transaction_id | ||
} | ||
}); | ||
Ok("Good".into()) | ||
} |
Oops, something went wrong.