瀏覽代碼

[fortuna] Fix config and CLI args (#1605)

* cleanup config

* merge configs

* more simplification

* move everything to config

* version bump

* nicer loading of secrets

* fix readme

* precommit

* fix

* precommit

* pr comments
Jayant Krishnamurthy 1 年之前
父節點
當前提交
8887a0908c

+ 1 - 1
apps/fortuna/Cargo.lock

@@ -1488,7 +1488,7 @@ dependencies = [
 
 [[package]]
 name = "fortuna"
-version = "5.4.5"
+version = "6.0.0"
 dependencies = [
  "anyhow",
  "axum",

+ 1 - 1
apps/fortuna/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name    = "fortuna"
-version = "5.4.5"
+version = "6.0.0"
 edition = "2021"
 
 [dependencies]

+ 9 - 12
apps/fortuna/README.md

@@ -3,8 +3,9 @@
 Fortuna is a webservice that serves random numbers according to the Entropy protocol.
 The webservice generates a hash chain of random numbers and reveals them to callers when permitted by the protocol.
 The hash chain is generated from a secret key that is provided to the server on startup.
+The service also operates a keeper task that performs callback transactions for user requests.
 
-A single instance of this webservice can simultaneously serve random numbers for several different blockchains.
+A single instance of this service can simultaneously serve random numbers for several different blockchains.
 Each blockchain is configured in `config.yaml`.
 
 ## Build & Test
@@ -21,20 +22,16 @@ registering a new randomness provider, or drawing a random value. To see the ava
 
 To start an instance of the webserver for local testing, you first need to perform a few setup steps:
 
-1. Create `config.yaml` file to point to the desired blockchains and Entropy contracts. Copy the content in `config.sample.yaml` to start with.
-1. Generate a secret key. The secret key is a 32-byte random value used to construct the hash chains.
-   You can generate this value using the `openssl` command:
-   `openssl rand -hex 32`
-1. Generate an ethereum wallet for the provider. You can do this in foundry using `cast wallet new`.
-   Note both the private key and the address; you will need both for subsequent steps.
-1. Register a randomness provider for this service: `cargo run -- register-provider --chain-id <chain id> --secret <secret> --private-key <private-key>`.
-   The chain id is the key of the blockchain in `config.yaml`, the secret is from step (2), and the private key is from step (3).
-   Note that you need to run this command once per blockchain configured in `config.yaml`.
+1. Create a `config.yaml` file to point to the desired blockchains and Entropy contracts. Copy the content in `config.sample.yaml` and follow the directions inside to generate the necessary private keys and secrets.
+1. Make sure the wallets you have generated in step (1) contain some gas tokens for the configured networks.
+1. Run `cargo run -- setup-provider` to register a randomness provider for this service. This command
+   will update the on-chain contracts such that the configured provider key is a randomness provider,
+   and its on-chain configuration matches `config.yaml`.
 
-Once you've completed the setup, simply run the following command, using the secret from step (2) and the wallet address from step (3) as the provider:
+Once you've completed the setup, simply run the following command to start the service:
 
 ```bash
-cargo run -- run --secret <secret> --provider <provider>
+RUST_LOG=INFO cargo run -- run
 ```
 
 This command will start the webservice on `localhost:34000`.

+ 39 - 0
apps/fortuna/config.sample.yaml

@@ -2,5 +2,44 @@ chains:
   lightlink_pegasus:
     geth_rpc_addr: https://replicator.pegasus.lightlink.io/rpc/v1
     contract_addr: 0x8250f4aF4B972684F7b336503E2D6dFeDeB1487a
+
+    # Keeper configuration for the chain
     reveal_delay_blocks: 0
     gas_limit: 500000
+
+    # Provider configuration
+    fee: 1500000000000000
+    # Historical commitments -- delete this block for local development purposes
+    commitments:
+      # prettier-ignore
+      - seed: [219,125,217,197,234,88,208,120,21,181,172,143,239,102,41,233,167,212,237,106,37,255,184,165,238,121,230,155,116,158,173,48]
+        chain_length: 10000
+        original_commitment_sequence_number: 104
+provider:
+  uri: http://localhost:8080/
+  chain_length: 100000
+
+  # An ethereum wallet address and private key. Generate with `cast wallet new`
+  address: 0xADDRESS
+  private_key:
+    # For local development, you can hardcode the private key here
+    value: 0xabcd
+    # For production, you can store the private key in a file.
+    # file: provider-key.txt
+  # A 32 byte random value in hexadecimal
+  # Generate with `openssl rand -hex 32`
+  secret:
+    # For local development, you can hardcode the value here
+    value: abcd
+    # For production, you can store the private key in a file.
+    # file: secret.txt
+keeper:
+  # An ethereum wallet address and private key for running the keeper service.
+  # This does not have to be the same key as the provider's key above.
+  # Generate with `cast wallet new`.
+  # The keeper private key can be omitted to run the webservice without the keeper.
+  private_key:
+    # For local development, you can hardcode the private key here
+    value: 0xabcd
+    # For production, you can store the private key in a file.
+    # file: keeper-key.txt

+ 0 - 8
apps/fortuna/provider-config.sample.yaml

@@ -1,8 +0,0 @@
-chains:
-  lightlink-pegasus:
-    commitments:
-      # prettier-ignore
-      - seed: [219,125,217,197,234,88,208,120,21,181,172,143,239,102,41,233,167,212,237,106,37,255,184,165,238,121,230,155,116,158,173,48]
-        chain_length: 10000
-        original_commitment_sequence_number: 104
-    fee: 1500000000000000

+ 37 - 9
apps/fortuna/src/command/register_provider.rs

@@ -1,13 +1,22 @@
 use {
     crate::{
+        api::{
+            get_register_uri,
+            ChainId,
+        },
         chain::ethereum::SignablePythContract,
         config::{
             Config,
+            EthereumConfig,
+            ProviderConfig,
             RegisterProviderOptions,
         },
         state::PebbleHashChain,
     },
-    anyhow::Result,
+    anyhow::{
+        anyhow,
+        Result,
+    },
     ethers::{
         abi::Bytes,
         signers::{
@@ -28,27 +37,45 @@ pub struct CommitmentMetadata {
 /// Register as a randomness provider. This method will generate and commit to a new random
 /// hash chain from the configured secret & a newly generated random value.
 pub async fn register_provider(opts: &RegisterProviderOptions) -> Result<()> {
-    let chain_config = Config::load(&opts.config.config)?.get_chain_config(&opts.chain_id)?;
+    let config = Config::load(&opts.config.config)?;
+    let chain_config = config.get_chain_config(&opts.chain_id)?;
+
+    register_provider_from_config(&config.provider, &opts.chain_id, &chain_config).await?;
+
+    Ok(())
+}
+
+pub async fn register_provider_from_config(
+    provider_config: &ProviderConfig,
+    chain_id: &ChainId,
+    chain_config: &EthereumConfig,
+) -> Result<()> {
+    let private_key_string = provider_config.private_key.load()?.ok_or(anyhow!(
+        "Please specify a provider private key in the config"
+    ))?;
 
     // Initialize a Provider to interface with the EVM contract.
     let contract =
-        Arc::new(SignablePythContract::from_config(&chain_config, &opts.private_key).await?);
+        Arc::new(SignablePythContract::from_config(&chain_config, &private_key_string).await?);
     // Create a new random hash chain.
     let random = rand::random::<[u8; 32]>();
-    let secret = opts.randomness.load_secret()?;
+    let secret = provider_config
+        .secret
+        .load()?
+        .ok_or(anyhow!("Please specify a provider secret in the config"))?;
 
-    let commitment_length = opts.randomness.chain_length;
+    let commitment_length = provider_config.chain_length;
     let mut chain = PebbleHashChain::from_config(
         &secret,
-        &opts.chain_id,
-        &opts.private_key.clone().parse::<LocalWallet>()?.address(),
+        &chain_id,
+        &private_key_string.parse::<LocalWallet>()?.address(),
         &chain_config.contract_addr,
         &random,
         commitment_length,
     )?;
 
     // Arguments to the contract to register our new provider.
-    let fee_in_wei = opts.fee;
+    let fee_in_wei = chain_config.fee;
     let commitment = chain.reveal()?;
     // Store the random seed and chain length in the metadata field so that we can regenerate the hash
     // chain at-will. (This is secure because you can't generate the chain unless you also have the secret)
@@ -56,6 +83,7 @@ pub async fn register_provider(opts: &RegisterProviderOptions) -> Result<()> {
         seed:         random,
         chain_length: commitment_length,
     };
+    let uri = get_register_uri(&provider_config.uri, &chain_id)?;
     let call = contract.register(
         fee_in_wei,
         commitment,
@@ -63,7 +91,7 @@ pub async fn register_provider(opts: &RegisterProviderOptions) -> Result<()> {
         commitment_length,
         // Use Bytes to serialize the uri. Most users will be using JS/TS to deserialize this uri.
         // Bincode is a different encoding mechanisms, and I didn't find any JS/TS library to parse bincode.
-        Bytes::from(opts.uri.as_str()).into(),
+        Bytes::from(uri.as_str()).into(),
     );
     let mut gas_estimate = call.estimate_gas().await?;
     let gas_multiplier = U256::from(2); //TODO: smarter gas estimation

+ 32 - 12
apps/fortuna/src/command/run.rs

@@ -11,7 +11,6 @@ use {
             Commitment,
             Config,
             EthereumConfig,
-            ProviderConfig,
             RunOptions,
         },
         keeper,
@@ -32,7 +31,10 @@ use {
             Http,
             Provider,
         },
-        types::BlockNumber,
+        types::{
+            Address,
+            BlockNumber,
+        },
     },
     prometheus_client::{
         encoding::EncodeLabelSet,
@@ -150,12 +152,15 @@ pub async fn run_keeper(
 
 pub async fn run(opts: &RunOptions) -> Result<()> {
     let config = Config::load(&opts.config.config)?;
-    let secret = opts.randomness.load_secret()?;
+    let secret = config.provider.secret.load()?.ok_or(anyhow!(
+        "Please specify a provider secret in the config file."
+    ))?;
     let (tx_exit, rx_exit) = watch::channel(false);
 
     let mut chains: HashMap<ChainId, BlockchainState> = HashMap::new();
     for (chain_id, chain_config) in &config.chains {
-        let state = setup_chain_state(&opts, &secret, chain_id, chain_config).await;
+        let state =
+            setup_chain_state(&config.provider.address, &secret, chain_id, chain_config).await;
         match state {
             Ok(state) => {
                 chains.insert(chain_id.clone(), state);
@@ -184,13 +189,15 @@ pub async fn run(opts: &RunOptions) -> Result<()> {
 
     let metrics_registry = Arc::new(RwLock::new(Registry::default()));
 
-    if let Some(keeper_private_key) = opts.load_keeper_private_key()? {
+    if let Some(keeper_private_key) = config.keeper.private_key.load()? {
         spawn(run_keeper(
             chains.clone(),
             config.clone(),
             keeper_private_key,
             metrics_registry.clone(),
         ));
+    } else {
+        tracing::info!("Not starting keeper service: no keeper private key specified. Please add one to the config if you would like to run the keeper service.")
     }
 
     // Spawn a thread to track latest block lag. This helps us know if the rpc is up and updated with the latest block.
@@ -202,16 +209,19 @@ pub async fn run(opts: &RunOptions) -> Result<()> {
 }
 
 async fn setup_chain_state(
-    opts: &&RunOptions,
+    provider: &Address,
     secret: &String,
     chain_id: &ChainId,
     chain_config: &EthereumConfig,
 ) -> Result<BlockchainState> {
-    let provider_config = ProviderConfig::load(&opts.provider_config.provider_config)?;
     let contract = Arc::new(PythContract::from_config(&chain_config)?);
-    let provider_chain_config = provider_config.get_chain_config(chain_id)?;
-    let mut provider_commitments = provider_chain_config.get_sorted_commitments();
-    let provider_info = contract.get_provider_info(opts.provider).call().await?;
+    let mut provider_commitments = chain_config.commitments.clone().unwrap_or(Vec::new());
+    provider_commitments.sort_by(|c1, c2| {
+        c1.original_commitment_sequence_number
+            .cmp(&c2.original_commitment_sequence_number)
+    });
+
+    let provider_info = contract.get_provider_info(*provider).call().await?;
     let latest_metadata = bincode::deserialize::<CommitmentMetadata>(
         &provider_info.commitment_metadata,
     )
@@ -223,6 +233,16 @@ async fn setup_chain_state(
         )
     })?;
 
+    let last_prior_commitment = provider_commitments.last();
+    if last_prior_commitment.is_some()
+        && last_prior_commitment
+            .unwrap()
+            .original_commitment_sequence_number
+            >= provider_info.original_commitment_sequence_number
+    {
+        return Err(anyhow!("The current hash chain for chain id {} has configured commitments for sequence numbers greater than the current on-chain sequence number. Are the commitments configured correctly?", &chain_id));
+    }
+
     provider_commitments.push(Commitment {
         seed:                                latest_metadata.seed,
         chain_length:                        latest_metadata.chain_length,
@@ -243,7 +263,7 @@ async fn setup_chain_state(
         let pebble_hash_chain = PebbleHashChain::from_config(
             &secret,
             &chain_id,
-            &opts.provider,
+            &provider,
             &chain_config.contract_addr,
             &commitment.seed,
             commitment.chain_length,
@@ -268,7 +288,7 @@ async fn setup_chain_state(
         id: chain_id.clone(),
         state: Arc::new(chain_state),
         contract,
-        provider_address: opts.provider,
+        provider_address: provider.clone(),
         reveal_delay_blocks: chain_config.reveal_delay_blocks,
         confirmed_block_status: chain_config.confirmed_block_status,
     };

+ 18 - 24
apps/fortuna/src/command/setup_provider.rs

@@ -8,15 +8,13 @@ use {
             ProviderInfo,
             SignablePythContract,
         },
-        command::{
-            register_provider,
-            register_provider::CommitmentMetadata,
+        command::register_provider::{
+            register_provider_from_config,
+            CommitmentMetadata,
         },
         config::{
             Config,
             EthereumConfig,
-            ProviderConfig,
-            RegisterProviderOptions,
             SetupProviderOptions,
         },
         state::{
@@ -44,7 +42,7 @@ use {
 pub async fn setup_provider(opts: &SetupProviderOptions) -> Result<()> {
     let config = Config::load(&opts.config.config)?;
     for (chain_id, chain_config) in &config.chains {
-        setup_chain_provider(opts, chain_id, chain_config).await?;
+        setup_chain_provider(&config, &chain_id, &chain_config).await?;
     }
     Ok(())
 }
@@ -58,15 +56,17 @@ pub async fn setup_provider(opts: &SetupProviderOptions) -> Result<()> {
 /// 5. Update provider uri if there is a mismatch with the uri set on contract.
 #[tracing::instrument(name="setup_chain_provider", skip_all, fields(chain_id=chain_id))]
 async fn setup_chain_provider(
-    opts: &SetupProviderOptions,
+    config: &Config,
     chain_id: &ChainId,
     chain_config: &EthereumConfig,
 ) -> Result<()> {
     tracing::info!("Setting up provider for chain: {0}", chain_id);
-    let provider_config = ProviderConfig::load(&opts.provider_config.provider_config)?;
-    let private_key = opts.load_private_key()?;
+    let provider_config = &config.provider;
+    let private_key = provider_config.private_key.load()?.ok_or(anyhow!(
+        "Please specify a provider private key in the config file."
+    ))?;
     let provider_address = private_key.clone().parse::<LocalWallet>()?.address();
-    let provider_fee = provider_config.get_chain_config(chain_id)?.fee;
+    let provider_fee = chain_config.fee;
     // Initialize a Provider to interface with the EVM contract.
     let contract = Arc::new(SignablePythContract::from_config(&chain_config, &private_key).await?);
 
@@ -76,8 +76,6 @@ async fn setup_chain_provider(
 
     let mut register = false;
 
-    let uri = get_register_uri(&opts.base_uri, &chain_id)?;
-
     // This condition satisfies for both when there is no registration and when there are no
     // more random numbers left to request
     if provider_info.end_sequence_number <= provider_info.sequence_number {
@@ -98,14 +96,16 @@ async fn setup_chain_provider(
                     )
                 })?;
 
-        let secret = opts.randomness.load_secret()?;
+        let secret = provider_config.secret.load()?.ok_or(anyhow!(
+            "Please specify a provider secret in the config file."
+        ))?;
         let hash_chain = PebbleHashChain::from_config(
             &secret,
             &chain_id,
             &provider_address,
             &chain_config.contract_addr,
             &metadata.seed,
-            opts.randomness.chain_length,
+            provider_config.chain_length,
         )?;
         let chain_state = HashChainState {
             offsets:     vec![provider_info
@@ -125,21 +125,15 @@ async fn setup_chain_provider(
 
     if register {
         tracing::info!("Registering");
-        register_provider(&RegisterProviderOptions {
-            config: opts.config.clone(),
-            chain_id: chain_id.clone(),
-            private_key: private_key.clone(),
-            randomness: opts.randomness.clone(),
-            fee: provider_fee,
-            uri,
-        })
-        .await
-        .map_err(|e| anyhow!("Chain: {} - Failed to register provider: {}", &chain_id, e))?;
+        register_provider_from_config(&provider_config, &chain_id, &chain_config)
+            .await
+            .map_err(|e| anyhow!("Chain: {} - Failed to register provider: {}", &chain_id, e))?;
         tracing::info!("Registered");
     } else {
         sync_fee(&contract, &provider_info, provider_fee)
             .in_current_span()
             .await?;
+        let uri = get_register_uri(&provider_config.uri, &chain_id)?;
         sync_uri(&contract, &provider_info, uri)
             .in_current_span()
             .await?;

+ 70 - 70
apps/fortuna/src/config.rs

@@ -86,32 +86,11 @@ pub struct ConfigOptions {
     pub config: String,
 }
 
-#[derive(Args, Clone, Debug)]
-#[command(next_help_heading = "Randomness Options")]
-#[group(id = "Randomness")]
-pub struct RandomnessOptions {
-    /// Path to file containing a secret which is a 64-char hex string.
-    /// The secret is used for generating new hash chains
-    #[arg(long = "secret")]
-    #[arg(env = "FORTUNA_SECRET")]
-    pub secret_file: String,
-
-    /// The length of the hash chain to generate.
-    #[arg(long = "chain-length")]
-    #[arg(env = "FORTUNA_CHAIN_LENGTH")]
-    #[arg(default_value = "100000")]
-    pub chain_length: u64,
-}
-
-impl RandomnessOptions {
-    pub fn load_secret(&self) -> Result<String> {
-        return Ok((fs::read_to_string(&self.secret_file))?);
-    }
-}
-
 #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
 pub struct Config {
-    pub chains: HashMap<ChainId, EthereumConfig>,
+    pub chains:   HashMap<ChainId, EthereumConfig>,
+    pub provider: ProviderConfig,
+    pub keeper:   KeeperConfig,
 }
 
 impl Config {
@@ -159,65 +138,86 @@ pub struct EthereumConfig {
 
     /// The gas limit to use for entropy callback transactions.
     pub gas_limit: u64,
+
+    /// How much the provider charges for a request on this chain.
+    #[serde(default)]
+    pub fee: u128,
+
+    /// Historical commitments made by the provider.
+    pub commitments: Option<Vec<Commitment>>,
 }
 
-#[derive(Args, Clone, Debug)]
-#[command(next_help_heading = "Provider Config Options")]
-#[group(id = "ProviderConfig")]
-pub struct ProviderConfigOptions {
-    #[arg(long = "provider-config")]
-    #[arg(env = "FORTUNA_PROVIDER_CONFIG")]
-    pub provider_config: String,
+
+/// A commitment that the provider used to generate random numbers at some point in the past.
+/// These historical commitments need to be stored in the configuration to support transition points where
+/// the commitment changes. In theory, this information is stored on the blockchain, but unfortunately it
+/// is hard to retrieve from there.
+#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
+pub struct Commitment {
+    pub seed:                                [u8; 32],
+    pub chain_length:                        u64,
+    pub original_commitment_sequence_number: u64,
 }
 
+/// Configuration values that are common to a single provider (and shared across chains).
 #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
 pub struct ProviderConfig {
-    pub chains: HashMap<ChainId, ProviderChainConfig>,
-}
+    /// The URI where clients can retrieve random values from this provider,
+    /// i.e., wherever fortuna for this provider will be hosted.
+    pub uri: String,
 
-impl ProviderConfig {
-    pub fn load(path: &str) -> Result<ProviderConfig> {
-        // Open and read the YAML file
-        let yaml_content = fs::read_to_string(path)?;
-        let config: ProviderConfig = serde_yaml::from_str(&yaml_content)?;
-        Ok(config)
-    }
+    /// The public key of the provider whose requests the server will respond to.
+    pub address: Address,
 
-    /// Get the provider chain config. The method returns an Option for ProviderChainConfig.
-    /// We may not have past any commitments for a chain. For example, for a new chain
-    pub fn get_chain_config(&self, chain_id: &ChainId) -> Result<ProviderChainConfig> {
-        self.chains.get(chain_id).map(|x| x.clone()).ok_or(
-            anyhow!(
-                "Could not find chain id {} in provider configuration",
-                &chain_id
-            )
-            .into(),
-        )
-    }
+    /// The provider's private key, which is required to register, update the commitment,
+    /// or claim fees. This argument *will not* be loaded for commands that do not need
+    /// the private key (e.g., running the server).
+    pub private_key: SecretString,
+
+    /// The provider's secret which is a 64-char hex string.
+    /// The secret is used for generating new hash chains
+    pub secret: SecretString,
+
+    /// The length of the hash chain to generate.
+    pub chain_length: u64,
 }
 
+/// Configuration values for the keeper service that are shared across chains.
 #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
-pub struct ProviderChainConfig {
-    commitments: Option<Vec<Commitment>>,
-    pub fee:     u128,
+pub struct KeeperConfig {
+    /// If provided, the keeper will run alongside the Fortuna API service.
+    /// The private key is a 20-byte (40 char) hex encoded Ethereum private key.
+    /// This key is required to submit transactions for entropy callback requests.
+    /// This key *does not need to be a registered provider*. In particular, production deployments
+    /// should ensure this is a different key in order to reduce the severity of security breaches.
+    pub private_key: SecretString,
 }
 
-impl ProviderChainConfig {
-    /// Returns a clone of the commitments in the sorted order.
-    /// `HashChainState`  requires offsets to be in order.
-    pub fn get_sorted_commitments(&self) -> Vec<Commitment> {
-        let mut commitments = self.commitments.clone().unwrap_or(Vec::new());
-        commitments.sort_by(|c1, c2| {
-            c1.original_commitment_sequence_number
-                .cmp(&c2.original_commitment_sequence_number)
-        });
-        commitments
-    }
+// A secret is a string that can be provided either as a literal in the config,
+// or in a separate file. (The separate file option is useful for 1password mounting in production.)
+#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
+pub struct SecretString {
+    pub value: Option<String>,
+
+    // The name of a file containing the string to read. Note that the file contents is trimmed
+    // of leading/trailing whitespace when read.
+    pub file: Option<String>,
 }
 
-#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
-pub struct Commitment {
-    pub seed:                                [u8; 32],
-    pub chain_length:                        u64,
-    pub original_commitment_sequence_number: u64,
+impl SecretString {
+    pub fn load(&self) -> Result<Option<String>> {
+        match &self.value {
+            Some(v) => return Ok(Some(v.clone())),
+            _ => {}
+        }
+
+        match &self.file {
+            Some(v) => {
+                return Ok(Some(fs::read_to_string(v)?.trim().to_string()));
+            }
+            _ => {}
+        }
+
+        Ok(None)
+    }
 }

+ 1 - 1
apps/fortuna/src/config/generate.rs

@@ -15,7 +15,7 @@ pub struct GenerateOptions {
     #[command(flatten)]
     pub config: ConfigOptions,
 
-    /// Retrieve a randomness request to this provider
+    /// The chain on which to submit the random number generation request.
     #[arg(long = "chain-id")]
     #[arg(env = "FORTUNA_CHAIN_ID")]
     pub chain_id: ChainId,

+ 2 - 25
apps/fortuna/src/config/register_provider.rs

@@ -1,10 +1,7 @@
 use {
     crate::{
         api::ChainId,
-        config::{
-            ConfigOptions,
-            RandomnessOptions,
-        },
+        config::ConfigOptions,
     },
     clap::Args,
 };
@@ -16,28 +13,8 @@ pub struct RegisterProviderOptions {
     #[command(flatten)]
     pub config: ConfigOptions,
 
-    /// Retrieve a randomness request to this provider
+    /// Register the provider on this chain
     #[arg(long = "chain-id")]
     #[arg(env = "FORTUNA_CHAIN_ID")]
     pub chain_id: ChainId,
-
-    /// A 20-byte (40 char) hex encoded Ethereum private key.
-    /// This key is required to submit transactions (such as registering with the contract).
-    #[arg(long = "private-key")]
-    #[arg(env = "PRIVATE_KEY")]
-    pub private_key: String,
-
-    #[command(flatten)]
-    pub randomness: RandomnessOptions,
-
-    /// The fee to charge (in wei) for each requested random number
-    #[arg(long = "pyth-contract-fee")]
-    #[arg(default_value = "100")]
-    pub fee: u128,
-
-    /// The URI where clients can retrieve random values from this provider,
-    /// i.e., wherever fortuna for this provider will be hosted.
-    #[arg(long = "uri")]
-    #[arg(default_value = "")]
-    pub uri: String,
 }

+ 2 - 39
apps/fortuna/src/config/run.rs

@@ -1,16 +1,7 @@
 use {
-    crate::config::{
-        ConfigOptions,
-        ProviderConfigOptions,
-        RandomnessOptions,
-    },
-    anyhow::Result,
+    crate::config::ConfigOptions,
     clap::Args,
-    ethers::types::Address,
-    std::{
-        fs,
-        net::SocketAddr,
-    },
+    std::net::SocketAddr,
 };
 
 /// Run the webservice
@@ -19,37 +10,9 @@ pub struct RunOptions {
     #[command(flatten)]
     pub config: ConfigOptions,
 
-    #[command(flatten)]
-    pub provider_config: ProviderConfigOptions,
-
-    #[command(flatten)]
-    pub randomness: RandomnessOptions,
-
     /// Address and port the HTTP server will bind to.
     #[arg(long = "rpc-listen-addr")]
     #[arg(default_value = super::DEFAULT_RPC_ADDR)]
     #[arg(env = "RPC_ADDR")]
     pub addr: SocketAddr,
-
-    /// The public key of the provider whose requests the server will respond to.
-    #[arg(long = "provider")]
-    #[arg(env = "FORTUNA_PROVIDER")]
-    pub provider: Address,
-
-    /// If provided, the keeper will run alongside the Fortuna API service.
-    /// It should be a path to a file containing a 20-byte (40 char) hex encoded Ethereum private key.
-    /// This key is required to submit transactions for entropy callback requests.
-    /// This key should not be a registered provider.
-    #[arg(long = "keeper-private-key")]
-    #[arg(env = "KEEPER_PRIVATE_KEY")]
-    pub keeper_private_key_file: Option<String>,
-}
-
-impl RunOptions {
-    pub fn load_keeper_private_key(&self) -> Result<Option<String>> {
-        if let Some(ref keeper_private_key_file) = self.keeper_private_key_file {
-            return Ok(Some(fs::read_to_string(keeper_private_key_file)?));
-        }
-        return Ok(None);
-    }
 }

+ 1 - 30
apps/fortuna/src/config/setup_provider.rs

@@ -1,12 +1,6 @@
 use {
-    crate::config::{
-        ConfigOptions,
-        ProviderConfigOptions,
-        RandomnessOptions,
-    },
-    anyhow::Result,
+    crate::config::ConfigOptions,
     clap::Args,
-    std::fs,
 };
 
 #[derive(Args, Clone, Debug)]
@@ -15,27 +9,4 @@ use {
 pub struct SetupProviderOptions {
     #[command(flatten)]
     pub config: ConfigOptions,
-
-    #[command(flatten)]
-    pub provider_config: ProviderConfigOptions,
-
-    /// Path to a file containing a 20-byte (40 char) hex encoded Ethereum private key.
-    /// This key is required to submit transactions (such as registering with the contract).
-    #[arg(long = "private-key")]
-    #[arg(env = "PRIVATE_KEY")]
-    pub private_key_file: String,
-
-    #[command(flatten)]
-    pub randomness: RandomnessOptions,
-
-    /// The base URI for fortuna.
-    /// e.g., https://fortuna-staging.dourolabs.app
-    #[arg(long = "uri")]
-    pub base_uri: String,
-}
-
-impl SetupProviderOptions {
-    pub fn load_private_key(&self) -> Result<String> {
-        return Ok((fs::read_to_string(&self.private_key_file))?);
-    }
 }