Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: private keys support for testing #159

Merged
merged 18 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,7 @@ jobs:
arch: [
# build on native runners instead of using emulation
{platform: linux/amd64, runner: buildjet-8vcpu-ubuntu-2204},
# don't currently need arm builds
# {platform: linux/arm64, runner: buildjet-8vcpu-ubuntu-2204-arm}
{platform: linux/arm64, runner: buildjet-8vcpu-ubuntu-2204-arm}
]
runs-on: ${{ matrix.arch.runner }}
permissions:
Expand Down
28 changes: 1 addition & 27 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

188 changes: 188 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,191 @@ Before running the script, ensure you have the following installed:

- [Docker](https://www.docker.com/get-started) (required for running SchemaSpy)
- [Sqlx CLI](https://github.com/launchbadge/sqlx/tree/main/sqlx-cli) (required for running migrations)

## Configuration

The Fuel Block Committer is configured primarily through environment variables.

### Environment Variables

#### Ethereum (ETH) Configuration

- **`COMMITTER__ETH__L1_KEYS__MAIN`**

- **Description:** The Ethereum key authorized by the L1 fuel chain state contract to post block commitments.
- **Format:** `Kms(<KEY_ARN>)` or `Private(<PRIVATE_KEY>)`
- **Example:** `Kms(arn:aws:kms:us-east-1:123456789012:key/abcd-1234)`

- **`COMMITTER__ETH__L1_KEYS__BLOB`**

- **Description:** (Optional) The Ethereum key for posting L2 state to L1.
- **Format:** `Kms(<KEY_ARN>)` or `Private(<PRIVATE_KEY>)`
- **Example:** `Kms(arn:aws:kms:us-east-1:123456789012:key/efgh-5678)`

- **`COMMITTER__ETH__RPC`**

- **Description:** URL to the Ethereum RPC endpoint.
- **Example:** `https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID`

- **`COMMITTER__ETH__STATE_CONTRACT_ADDRESS`**
- **Description:** Ethereum address of the Fuel chain state contract.
- **Example:** `0xYourStateContractAddress`

#### Fuel Configuration

- **`COMMITTER__FUEL__GRAPHQL_ENDPOINT`**

- **Description:** URL to a Fuel Core GraphQL endpoint.
- **Example:** `http://localhost:4000/graphql`

- **`COMMITTER__FUEL__NUM_BUFFERED_REQUESTS`**
- **Description:** Number of concurrent http requests towards the fuel node.
- **Type:** Positive integer
- **Example:** `5`

#### Database (DB) Configuration

- **`COMMITTER__APP__DB__HOST`**

- **Description:** Hostname or IP address of the PostgreSQL server.
- **Example:** `localhost`

- **`COMMITTER__APP__DB__PORT`**

- **Description:** Port number on which the PostgreSQL server is listening.
- **Type:** `u16`
- **Example:** `5432`

- **`COMMITTER__APP__DB__USERNAME`**

- **Description:** Username for authenticating with the PostgreSQL server.
- **Example:** `username`

- **`COMMITTER__APP__DB__PASSWORD`**

- **Description:** Password for authenticating with the PostgreSQL server.
- **Example:** `password`

- **`COMMITTER__APP__DB__DATABASE`**

- **Description:** Name of the database to connect to on the PostgreSQL server.
- **Example:** `fuel_db`

- **`COMMITTER__APP__DB__MAX_CONNECTIONS`**

- **Description:** Maximum number of connections allowed in the connection pool.
- **Type:** `u32`
- **Example:** `10`

- **`COMMITTER__APP__DB__USE_SSL`**
- **Description:** Whether to use SSL when connecting to the PostgreSQL server.
- **Type:** `bool`
- **Values:** `true` or `false`
- **Example:** `false`

#### Application (App) Configuration

- **`COMMITTER__APP__PORT`**

- **Description:** Port used by the started server.
- **Type:** `u16`
- **Example:** `8080`

- **`COMMITTER__APP__HOST`**

- **Description:** IPv4 address on which the server will listen for connections.
- **Example:** `127.0.0.1`

- **`COMMITTER__APP__BLOCK_CHECK_INTERVAL`**

- **Description:** How often to check for new fuel blocks.
- **Format:** Human-readable duration (e.g., `5s`, `1m`)
- **Example:** `5s`

- **`COMMITTER__APP__TX_FINALIZATION_CHECK_INTERVAL`**

- **Description:** How often to check for finalized L1 transactions.
- **Format:** Human-readable duration
- **Example:** `5s`

- **`COMMITTER__APP__NUM_BLOCKS_TO_FINALIZE_TX`**

- **Description:** Number of L1 blocks that need to pass to accept the transaction as finalized.
- **Type:** `u64`
- **Example:** `3`

- **`COMMITTER__APP__GAS_BUMP_TIMEOUT`**

- **Description:** Interval after which to bump a pending transaction.
- **Format:** Human-readable duration
- **Example:** `300s`

- **`COMMITTER__APP__TX_MAX_FEE`**

- **Description:** Maximum gas fee permitted for a transaction in wei.
- **Type:** `u64`
- **Example:** `4000000000000000`

- **`COMMITTER__APP__SEND_TX_REQUEST_TIMEOUT`**
- **Description:** Duration for timeout when sending transaction requests.
- **Format:** Human-readable duration
- **Example:** `10s`

#### Bundle Configuration

- **`COMMITTER__APP__BUNDLE__ACCUMULATION_TIMEOUT`**

- **Description:** Duration to wait for additional fuel blocks before initiating the bundling process.
- **Format:** Human-readable duration
- **Example:** `30s`

- **`COMMITTER__APP__BUNDLE__BLOCKS_TO_ACCUMULATE`**

- **Description:** Number of fuel blocks to accumulate before initiating the bundling process.
- **Type:** Positive integer
- **Example:** `5`

- **`COMMITTER__APP__BUNDLE__OPTIMIZATION_TIMEOUT`**

- **Description:** Maximum duration allocated for determining the optimal bundle size.
- **Format:** Human-readable duration
- **Example:** `60s`

- **`COMMITTER__APP__BUNDLE__COMPRESSION_LEVEL`**

- **Description:** Compression level used for compressing block data before submission.
- **Values:** `"disabled"`, `"min"`, `"level1"`..`"level9"`, `"max"`
- **Example:** `"min"`

- **`COMMITTER__APP__BUNDLE__OPTIMIZATION_STEP`**

- **Description:** Size of the optimization step at the start of the optimization process.
- **Type:** Positive integer (`NonZeroUsize`)
- **Example:** `100`

- **`COMMITTER__APP__BUNDLE__FRAGMENTS_TO_ACCUMULATE`**

- **Description:** Number of fragments to accumulate before submitting them in a transaction to L1.
- **Type:** Positive integer (`NonZeroUsize`)
- **Example:** `6`

- **`COMMITTER__APP__BUNDLE__FRAGMENT_ACCUMULATION_TIMEOUT`**

- **Description:** Duration to wait for additional fragments before submitting them.
- **Format:** Human-readable duration
- **Example:** `30s`

- **`COMMITTER__APP__BUNDLE__NEW_BUNDLE_CHECK_INTERVAL`**
- **Description:** Duration to wait before checking if a new bundle can be made.
- **Format:** Human-readable duration
- **Example:** `15s`

### Configuration Validation

The committer performs validation on the provided configuration to ensure consistency and correctness. For example:

- **Wallet Keys:** The main wallet key and blob pool wallet key must be different.
- **Fragments to Accumulate:** Must be less than or equal to 6.
- **Block Height Lookback:** Must be greater than or equal to the number of blocks to accumulate.

If any validation fails, the committer will return an error, preventing it from running with invalid settings.
2 changes: 1 addition & 1 deletion committer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ rust-version = { workspace = true }
actix-web = { workspace = true, features = ["macros"] }
clap = { workspace = true, features = ["default", "derive"] }
clock = { workspace = true }
config = { workspace = true, features = ["toml", "async"] }
config = { workspace = true, features = ["async"] }
eth = { workspace = true }
fuel = { workspace = true }
fuel-block-committer-encoding = { workspace = true }
Expand Down
23 changes: 12 additions & 11 deletions committer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
};

use clap::{command, Parser};
use eth::Address;
use eth::{Address, L1Keys};
use fuel_block_committer_encoding::bundle::CompressionLevel;
use serde::Deserialize;
use storage::DbConfig;
Expand All @@ -21,12 +21,15 @@ pub struct Config {

impl Config {
pub fn validate(&self) -> crate::errors::Result<()> {
if let Some(blob_pool_wallet_key) = &self.eth.blob_pool_key_arn {
if blob_pool_wallet_key == &self.eth.main_key_arn {
return Err(crate::errors::Error::Other(
"Wallet key and blob pool wallet key must be different".to_string(),
));
}
let keys = &self.eth.l1_keys;
if keys
.blob
.as_ref()
.is_some_and(|blob_key| blob_key == &keys.main)
{
return Err(crate::errors::Error::Other(
"Wallet key and blob pool wallet key must be different".to_string(),
));
}

if self.app.bundle.fragments_to_accumulate.get() > 6 {
Expand Down Expand Up @@ -56,10 +59,8 @@ pub struct Fuel {

#[derive(Debug, Clone, Deserialize)]
pub struct Eth {
/// The AWS KMS key ID authorized by the L1 bridging contracts to post block commitments.
pub main_key_arn: String,
/// The AWS KMS key ID for posting L2 state to L1.
pub blob_pool_key_arn: Option<String>,
/// L1 keys for calling the state contract and for posting state
pub l1_keys: L1Keys,
/// URL to a Ethereum RPC endpoint.
#[serde(deserialize_with = "parse_url")]
pub rpc: Url,
Expand Down
2 changes: 1 addition & 1 deletion committer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ async fn main() -> Result<()> {

// If the blob pool wallet key is set, we need to start
// the state committer and state importer
if config.eth.blob_pool_key_arn.is_some() {
if config.eth.l1_keys.blob.is_some() {
let block_bundler = setup::block_bundler(
fuel_adapter.clone(),
storage.clone(),
Expand Down
14 changes: 3 additions & 11 deletions committer/src/setup.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{num::NonZeroU32, time::Duration};

use clock::SystemClock;
use eth::{AwsConfig, BlobEncoder, KmsKeys};
use eth::{BlobEncoder, Signers};
use fuel_block_committer_encoding::bundle;
use metrics::{
prometheus::{IntGauge, Registry},
Expand All @@ -13,7 +13,7 @@ use tokio::task::JoinHandle;
use tokio_util::sync::CancellationToken;
use tracing::{error, info};

use crate::{config, errors::Result, AwsClient, Database, FuelApi, L1};
use crate::{config, errors::Result, Database, FuelApi, L1};

pub fn wallet_balance_tracker(
internal_config: &config::Internal,
Expand Down Expand Up @@ -190,19 +190,11 @@ pub async fn l1_adapter(
internal_config: &config::Internal,
registry: &Registry,
) -> Result<(L1, HealthChecker)> {
let aws_config = AwsConfig::from_env().await;

let aws_client = AwsClient::new(aws_config);

let l1 = L1::connect(
config.eth.rpc.clone(),
config.eth.state_contract_address,
KmsKeys {
main_key_arn: config.eth.main_key_arn.clone(),
blob_pool_key_arn: config.eth.blob_pool_key_arn.clone(),
},
Signers::for_keys(config.eth.l1_keys.clone()).await?,
internal_config.eth_errors_before_unhealthy,
aws_client,
eth::TxConfig {
tx_max_fee: config.app.tx_max_fee as u128,
send_tx_request_timeout: config.app.send_tx_request_timeout,
Expand Down
8 changes: 5 additions & 3 deletions e2e/src/committer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ impl Committer {
let db_port = get_field!(db_port);
let db_name = get_field!(db_name);

let main_key = format!("Kms({})", get_field!(main_key_arn));
let blob_key = self.blob_key_arn.map(|k| format!("Kms({k})"));
cmd.env("E2E_TEST_AWS_ENDPOINT", kms_url)
.env("AWS_REGION", "us-east-1")
.env("AWS_ACCESS_KEY_ID", "test")
.env("AWS_SECRET_ACCESS_KEY", "test")
.env("COMMITTER__ETH__MAIN_KEY_ARN", get_field!(main_key_arn))
.env("COMMITTER__ETH__L1_KEYS__MAIN", main_key)
.env("COMMITTER__ETH__RPC", get_field!(eth_rpc).as_str())
.env(
"COMMITTER__ETH__STATE_CONTRACT_ADDRESS",
Expand Down Expand Up @@ -112,8 +114,8 @@ impl Committer {
.current_dir(Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap())
.kill_on_drop(true);

if let Some(blob_wallet_key_arn) = self.blob_key_arn {
cmd.env("COMMITTER__ETH__BLOB_POOL_KEY_ARN", blob_wallet_key_arn);
if let Some(key) = blob_key {
cmd.env("COMMITTER__ETH__L1_KEYS__BLOB", key);
}

let sink = if self.show_logs {
Expand Down
Loading
Loading