Skip to content

Commit

Permalink
Merge pull request #379 from eqlabs/feat_add_sequencer_url_config
Browse files Browse the repository at this point in the history
feat: support sequencer url configuration
  • Loading branch information
Mirko-von-Leipzig authored Jun 15, 2022
2 parents 8ed0ac7 + c663ab1 commit d1033d9
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 7 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ The configuration file uses the `toml` format:
http-rpc = "127.0.0.1:1235"
# The directory the node will use to store its data. Defaults to the current directory.
data-directory = "..."
# Override the Sequencer gateway address with your own. This is can be useful if you
# have a caching proxy in front of the actual Sequencer gateway. If you're unsure
# of what this does, then you don't need it.
sequencer-url = "https://..."

[ethereum]
# This is required and must be an HTTP(s) URL pointing to your Ethereum node's endpoint.
Expand Down
22 changes: 17 additions & 5 deletions crates/pathfinder/src/bin/pathfinder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,37 @@ async fn main() -> anyhow::Result<()> {
let eth_transport =
HttpTransport::from_config(config.ethereum).context("Creating Ethereum transport")?;

let network_chain = eth_transport
let ethereum_chain = eth_transport
.chain()
.await
.context("Determining Ethereum chain")?;

let database_path = config.data_directory.join(match network_chain {
let database_path = config.data_directory.join(match ethereum_chain {
ethereum::Chain::Mainnet => "mainnet.sqlite",
ethereum::Chain::Goerli => "goerli.sqlite",
});
let storage = Storage::migrate(database_path.clone()).unwrap();
info!(location=?database_path, "Database migrated.");

let sequencer = sequencer::Client::new(network_chain).unwrap();
let sequencer = match config.sequencer_url {
Some(url) => {
info!(?url, "Using custom Sequencer address");
let client = sequencer::Client::with_url(url).unwrap();
let sequencer_chain = client.chain().await.unwrap();
if sequencer_chain != ethereum_chain {
tracing::error!(sequencer=%sequencer_chain, ethereum=%ethereum_chain, "Sequencer and Ethereum network mismatch");
anyhow::bail!("Sequencer and Ethereum network mismatch. Sequencer is on {sequencer_chain} but Ethereum is on {ethereum_chain}");
}
client
}
None => sequencer::Client::new(ethereum_chain).unwrap(),
};
let sync_state = Arc::new(state::SyncState::default());

let sync_handle = tokio::spawn(state::sync(
storage.clone(),
eth_transport,
network_chain,
ethereum_chain,
sequencer.clone(),
sync_state.clone(),
state::l1::sync,
Expand All @@ -69,7 +81,7 @@ async fn main() -> anyhow::Result<()> {
"Creating python process for call handling. Have you setup our Python dependencies?",
)?;

let api = rpc::api::RpcApi::new(storage, sequencer, network_chain, sync_state)
let api = rpc::api::RpcApi::new(storage, sequencer, ethereum_chain, sync_state)
.with_call_handling(call_handle);

let (rpc_handle, local_addr) = rpc::run_server(config.http_rpc_addr, api)
Expand Down
5 changes: 5 additions & 0 deletions crates/pathfinder/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pub enum ConfigOption {
HttpRpcAddress,
/// Path to the node's data directory.
DataDirectory,
/// The Sequencer's HTTP URL.
SequencerHttpUrl,
}

impl Display for ConfigOption {
Expand All @@ -30,6 +32,7 @@ impl Display for ConfigOption {
ConfigOption::EthereumPassword => f.write_str("Ethereum password"),
ConfigOption::DataDirectory => f.write_str("Data directory"),
ConfigOption::HttpRpcAddress => f.write_str("HTTP-RPC socket address"),
ConfigOption::SequencerHttpUrl => f.write_str("Sequencer HTTP URL"),
}
}
}
Expand All @@ -52,6 +55,8 @@ pub struct Configuration {
pub http_rpc_addr: SocketAddr,
/// The node's data directory.
pub data_directory: PathBuf,
/// The Sequencer's HTTP URL.
pub sequencer_url: Option<Url>,
}

impl Configuration {
Expand Down
14 changes: 14 additions & 0 deletions crates/pathfinder/src/config/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@ impl ConfigBuilder {

// Optional parameters.
let eth_password = self.take(ConfigOption::EthereumPassword);
let sequencer_url = match self.take(ConfigOption::SequencerHttpUrl) {
Some(url) => {
let url = url.parse::<Url>().map_err(|err| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Invalid Sequencer URL ({}): {}", url, err),
)
})?;

Some(url)
}
None => None,
};

// Optional parameters with defaults.
let data_directory = self
Expand Down Expand Up @@ -79,6 +92,7 @@ impl ConfigBuilder {
},
http_rpc_addr,
data_directory,
sequencer_url,
})
}

Expand Down
36 changes: 35 additions & 1 deletion crates/pathfinder/src/config/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const DATA_DIR_KEY: &str = "data-directory";
const ETH_URL_KEY: &str = "ethereum.url";
const ETH_PASS_KEY: &str = "ethereum.password";
const HTTP_RPC_ADDR_KEY: &str = "http-rpc";
const SEQ_URL_KEY: &str = "sequencer-url";

/// Parses the cmd line arguments and returns the optional
/// configuration file's path and the specified configuration options.
Expand Down Expand Up @@ -40,12 +41,14 @@ where
let ethereum_url = args.value_of(ETH_URL_KEY).map(|s| s.to_owned());
let ethereum_password = args.value_of(ETH_PASS_KEY).map(|s| s.to_owned());
let http_rpc_addr = args.value_of(HTTP_RPC_ADDR_KEY).map(|s| s.to_owned());
let sequencer_url = args.value_of(SEQ_URL_KEY).map(|s| s.to_owned());

let cfg = ConfigBuilder::default()
.with(ConfigOption::EthereumHttpUrl, ethereum_url)
.with(ConfigOption::EthereumPassword, ethereum_password)
.with(ConfigOption::HttpRpcAddress, http_rpc_addr)
.with(ConfigOption::DataDirectory, data_directory);
.with(ConfigOption::DataDirectory, data_directory)
.with(ConfigOption::SequencerHttpUrl, sequencer_url);

Ok((config_filepath, cfg))
}
Expand Down Expand Up @@ -107,6 +110,15 @@ Examples:
.value_name("PATH")
.env("PATHFINDER_DATA_DIRECTORY")
)
.arg(
Arg::new(SEQ_URL_KEY)
.long(SEQ_URL_KEY)
.help("Sequencer REST API endpoint")
.long_help("Lets you customise the Sequencer address. Useful if you have a proxy in front of the Sequencer.")
.takes_value(true)
.value_name("HTTP(s) URL")
.env("PATHFINDER_SEQUENCER_URL")
)
}

#[cfg(test)]
Expand All @@ -126,6 +138,7 @@ mod tests {
env::remove_var("PATHFINDER_ETHEREUM_API_URL");
env::remove_var("PATHFINDER_HTTP_RPC_ADDRESS");
env::remove_var("PATHFINDER_DATA_DIRECTORY");
env::remove_var("PATHFINDER_SEQUENCER_URL");
}

#[test]
Expand Down Expand Up @@ -232,6 +245,27 @@ mod tests {
assert_eq!(cfg.take(ConfigOption::DataDirectory), Some(value));
}

#[test]
fn sequencer_url_long() {
let _env_guard = ENV_VAR_MUTEX.lock().unwrap_or_else(|e| e.into_inner());
clear_environment();

let value = "value".to_owned();
let (_, mut cfg) = parse_args(vec!["bin name", "--sequencer-url", &value]).unwrap();
assert_eq!(cfg.take(ConfigOption::SequencerHttpUrl), Some(value));
}

#[test]
fn sequencer_url_environment_variable() {
let _env_guard = ENV_VAR_MUTEX.lock().unwrap_or_else(|e| e.into_inner());
clear_environment();

let value = "value".to_owned();
env::set_var("PATHFINDER_SEQUENCER_URL", &value);
let (_, mut cfg) = parse_args(vec!["bin name"]).unwrap();
assert_eq!(cfg.take(ConfigOption::SequencerHttpUrl), Some(value));
}

#[test]
fn empty_config() {
let _env_guard = ENV_VAR_MUTEX.lock().unwrap_or_else(|e| e.into_inner());
Expand Down
11 changes: 11 additions & 0 deletions crates/pathfinder/src/config/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ struct FileConfig {
http_rpc: Option<String>,
#[serde(rename = "data-directory")]
data_directory: Option<String>,
#[serde(rename = "sequencer-url")]
sequencer_url: Option<String>,
}

impl FileConfig {
Expand All @@ -29,6 +31,7 @@ impl FileConfig {
}
.with(ConfigOption::DataDirectory, self.data_directory)
.with(ConfigOption::HttpRpcAddress, self.http_rpc)
.with(ConfigOption::SequencerHttpUrl, self.sequencer_url)
}
}

Expand Down Expand Up @@ -98,6 +101,14 @@ password = "{}""#,
assert_eq!(cfg.take(ConfigOption::DataDirectory), Some(value));
}

#[test]
fn sequencer_url() {
let value = "value".to_owned();
let toml = format!(r#"sequencer-url = "{}""#, value);
let mut cfg = config_from_str(&toml).unwrap();
assert_eq!(cfg.take(ConfigOption::SequencerHttpUrl), Some(value));
}

#[test]
fn empty_config() {
let cfg = config_from_str("").unwrap();
Expand Down
9 changes: 9 additions & 0 deletions crates/pathfinder/src/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ pub enum Chain {
Goerli,
}

impl std::fmt::Display for Chain {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Chain::Mainnet => f.write_str("Mainnet"),
Chain::Goerli => f.write_str("Görli"),
}
}
}

/// List of semi-official Ethereum RPC errors taken from [EIP-1474] (which is stagnant).
///
/// The issue of standardizing the Ethereum RPC seems to now be taking
Expand Down
Loading

0 comments on commit d1033d9

Please sign in to comment.