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(sidecar): quick deployment script with systemctl #176

Merged
merged 3 commits into from
Jul 31, 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
17 changes: 17 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,23 @@ _build-sidecar:
_build-mevboost:
cd mev-boost && docker buildx build -t ghcr.io/chainbound/bolt-mev-boost:0.1.0 . --load

# deploy the bolt sidecar to the dev server
deploy-sidecar-dev:
chmod +x ./scripts/deploy_bolt_sidecar.sh && ./scripts/deploy_bolt_sidecar.sh

# Check the status of the sidecar service on the dev server
status-sidecar-dev:
ssh shared@remotebeast "sudo systemctl status bolt_sidecar" | less

# Tail the logs of the service on the dev server
logs-sidecar-dev:
ssh shared@remotebeast "journalctl -qu bolt_sidecar -f"

# Stop the service on the dev server
stop-sidecar-dev:
ssh shared@remotebeast "sudo systemctl stop bolt_sidecar"


# build and push the docker images to the github container registry with the provided tag
[confirm("are you sure? this will build and push new images on ghcr.io")]
release tag:
Expand Down
26 changes: 26 additions & 0 deletions bolt-sidecar/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

# node + PBS URLs
BOLT_SIDECAR_EXECUTION_API_URL=http://localhost:4485
BOLT_SIDECAR_BEACON_API_URL=http://localhost:4400
BOLT_SIDECAR_ENGINE_API_URL=http://localhost:4451
BOLT_SIDECAR_MEVBOOST_URL=http://localhost:19550

# server ports
BOLT_SIDECAR_PORT=8000
BOLT_SIDECAR_MEVBOOST_PROXY_PORT=18551

# commitment limits
BOLT_SIDECAR_MAX_COMMITMENTS=128
BOLT_SIDECAR_MAX_COMMITTED_GAS=10000000

# chain configs
BOLT_SIDECAR_CHAIN=helder
BOLT_SIDECAR_COMMITMENT_DEADLINE=8000
BOLT_SIDECAR_SLOT_TIME=12

# sidecar security configs
BOLT_SIDECAR_VALIDATOR_INDEXES=
BOLT_SIDECAR_JWT_HEX=
BOLT_SIDECAR_FEE_RECIPIENT=
BOLT_SIDECAR_BUILDER_PRIVATE_KEY=
BOLT_SIDECAR_PRIVATE_KEY=
3 changes: 2 additions & 1 deletion bolt-sidecar/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
target/
.env
.env
.env.dev
2 changes: 1 addition & 1 deletion bolt-sidecar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ default-run = "bolt-sidecar"

[dependencies]
# core
clap = { version = "4.5.4", features = ["derive"] }
clap = { version = "4.5.4", features = ["derive", "env"] }
tokio = { version = "1", features = ["full"] }
axum = { version = "0.7", features = ["macros"] }
axum-extra = "0.9.3"
Expand Down
14 changes: 11 additions & 3 deletions bolt-sidecar/src/config/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,23 @@ const BUILDER_DOMAIN_HELDER: [u8; 32] =
#[derive(Debug, Clone, Args)]
pub struct ChainConfig {
/// Chain on which the sidecar is running
#[clap(short = 'C', long, default_value = "mainnet")]
#[clap(long, env = "BOLT_SIDECAR_CHAIN", default_value = "mainnet")]
chain: Chain,
/// The deadline in the slot at which the sidecar will stop accepting
/// new commitments for the next block (parsed as milliseconds).
#[clap(short = 'd', long, default_value_t = DEFAULT_COMMITMENT_DEADLINE_IN_MILLIS)]
#[clap(
long,
env = "BOLT_SIDECAR_COMMITMENT_DEADLINE",
default_value_t = DEFAULT_COMMITMENT_DEADLINE_IN_MILLIS)
]
commitment_deadline: u64,
/// The slot time duration in seconds. If provided,
/// it overrides the default for the selected [Chain].
#[clap(short = 's', long, default_value_t = DEFAULT_SLOT_TIME_IN_SECONDS)]
#[clap(
long,
env = "BOLT_SIDECAR_SLOT_TIME",
default_value_t = DEFAULT_SLOT_TIME_IN_SECONDS)
]
slot_time: u64,
}

Expand Down
35 changes: 17 additions & 18 deletions bolt-sidecar/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,48 +27,48 @@ pub const DEFAULT_MEV_BOOST_PROXY_PORT: u16 = 18551;
#[derive(Parser, Debug)]
pub struct Opts {
/// Port to listen on for incoming JSON-RPC requests
#[clap(short = 'p', long)]
#[clap(long, env = "BOLT_SIDECAR_PORT")]
pub(super) port: Option<u16>,
/// URL for the beacon client
#[clap(short = 'c', long)]
#[clap(long, env = "BOLT_SIDECAR_BEACON_API_URL")]
pub(super) beacon_api_url: String,
/// URL for the MEV-Boost sidecar client to use
#[clap(short = 'b', long)]
#[clap(long, env = "BOLT_SIDECAR_MEVBOOST_URL")]
pub(super) mevboost_url: String,
/// Execution client API URL
#[clap(short = 'x', long)]
#[clap(long, env = "BOLT_SIDECAR_EXECUTION_API_URL")]
pub(super) execution_api_url: String,
/// Execution client Engine API URL
#[clap(short = 'e', long)]
#[clap(long, env = "BOLT_SIDECAR_ENGINE_API_URL")]
pub(super) engine_api_url: String,
/// MEV-Boost proxy server port to use
#[clap(short = 'y', long)]
#[clap(long, env = "BOLT_SIDECAR_MEVBOOST_PROXY_PORT")]
pub(super) mevboost_proxy_port: u16,
/// Max number of commitments to accept per block
#[clap(short = 'm', long)]
#[clap(long, env = "BOLT_SIDECAR_MAX_COMMITMENTS")]
pub(super) max_commitments: Option<NonZero<usize>>,
/// Max committed gas per slot
#[clap(short = 'g', long)]
#[clap(long, env = "BOLT_SIDECAR_MAX_COMMITTED_GAS")]
pub(super) max_committed_gas: Option<NonZero<u64>>,
/// Validator indexes of connected validators that the sidecar
/// should accept commitments on behalf of. Accepted values:
/// - a comma-separated list of indexes (e.g. "1,2,3,4")
/// - a contiguous range of indexes (e.g. "1..4")
/// - a mix of the above (e.g. "1,2..4,6..8")
#[clap(short = 'v', long, value_parser = ValidatorIndexes::from_str)]
#[clap(long, value_parser = ValidatorIndexes::from_str, env = "BOLT_SIDECAR_VALIDATOR_INDEXES")]
pub(super) validator_indexes: ValidatorIndexes,
/// The JWT secret token to authenticate calls to the engine API.
///
/// It can either be a hex-encoded string or a file path to a file
/// containing the hex-encoded secret.
#[clap(short = 'j', long)]
#[clap(long, env = "BOLT_SIDECAR_JWT_HEX")]
pub(super) jwt_hex: String,
/// The fee recipient address for fallback blocks
#[clap(short = 'f', long)]
#[clap(long, env = "BOLT_SIDECAR_FEE_RECIPIENT")]
pub(super) fee_recipient: Address,
/// Secret BLS key to sign fallback payloads with
/// (If not provided, a random key will be used)
#[clap(short = 'K', long)]
#[clap(long, env = "BOLT_SIDECAR_BUILDER_PRIVATE_KEY")]
pub(super) builder_private_key: Option<String>,
/// Chain config for the chain on which the sidecar is running
#[clap(flatten)]
Expand Down Expand Up @@ -186,19 +186,18 @@ impl TryFrom<Opts> for Config {
.transpose()?;

config.private_key = if let Some(sk) = opts.signing.private_key {
// Check if the string starts with "0x" and remove it
let hex_sk = sk.strip_prefix("0x").unwrap_or(&sk);

let sk = SecretKey::from_bytes(&hex::decode(hex_sk)?)
.map_err(|e| eyre::eyre!("Failed decoding BLS secret key: {:?}", e))?;
.map_err(|e| eyre::eyre!("Failed decoding BLS signer secret key: {:?}", e))?;
Some(sk)
} else {
None
};

if let Some(builder_private_key) = opts.builder_private_key {
let sk = SecretKey::from_bytes(&hex::decode(builder_private_key)?)
.map_err(|e| eyre::eyre!("Failed decoding BLS secret key: {:?}", e))?;
if let Some(builder_sk) = opts.builder_private_key {
let hex_sk = builder_sk.strip_prefix("0x").unwrap_or(&builder_sk);
let sk = SecretKey::from_bytes(&hex::decode(hex_sk)?)
.map_err(|e| eyre::eyre!("Failed decoding BLS builder secret key: {:?}", e))?;
config.builder_private_key = sk;
}

Expand Down
12 changes: 10 additions & 2 deletions bolt-sidecar/src/config/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,17 @@ use clap::{ArgGroup, Args};
)]
pub struct SigningOpts {
/// Private key to use for signing preconfirmation requests
#[clap(short = 'k', long)]
#[clap(
long,
env = "BOLT_SIDECAR_PRIVATE_KEY",
conflicts_with("commit_boost_url")
)]
pub(super) private_key: Option<String>,
/// URL for the commit-boost sidecar
#[clap(short = 'B', long, conflicts_with("private_key"))]
#[clap(
long,
env = "BOLT_SIDECAR_COMMIT_BOOST_URL",
conflicts_with("private_key")
)]
pub(super) commit_boost_url: Option<String>,
}
8 changes: 7 additions & 1 deletion bolt-sidecar/src/state/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,6 @@ impl<C: StateFetcher> ExecutionState<C> {
//
// If the templates do not exist, or this is the first request for this sender,
// its diffs will be zero.
// TODO: why highest slot here?
let (nonce_diff, balance_diff, highest_slot_for_account) =
self.block_templates.iter().fold(
(0, U256::ZERO, 0),
Expand Down Expand Up @@ -333,6 +332,13 @@ impl<C: StateFetcher> ExecutionState<C> {
}
};

tracing::debug!(
?account_state,
?nonce_diff,
?balance_diff,
"Validating transaction"
);

let sender_nonce_diff = bundle_nonce_diff_map.entry(sender).or_insert(0);
let sender_balance_diff = bundle_balance_diff_map.entry(sender).or_insert(U256::ZERO);

Expand Down
12 changes: 12 additions & 0 deletions scripts/bolt_sidecar.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Unit]
Description=Bolt Sidecar Development Service
After=network.target

[Service]
User=shared
ExecStart=/usr/local/bin/bolt-sidecar
Restart=on-failure
EnvironmentFile=/home/shared/bolt_sidecar/.env.dev

[Install]
WantedBy=multi-user.target
24 changes: 24 additions & 0 deletions scripts/deploy_bolt_sidecar.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash

# This script is used to deploy the bolt_sidecar binary as a service on
# our remote dev server. Requirements:
# - Access to Chainbound's Tailnet dev server "remotebeast"
# - A .env.dev file in the bolt_sidecar directory, filled with the necessary vars

set -e

# check if ".env.dev" exists. if not, exit with error
test -f ./bolt-sidecar/.env.dev || (echo "No .env.dev file found. Exiting." && exit 1)

# copy the files to the remote dev server
rsync -av --exclude target --exclude .git ./bolt-sidecar/ shared@remotebeast:/home/shared/bolt_sidecar
rsync -av ./scripts/bolt_sidecar.service shared@remotebeast:/home/shared/bolt_sidecar/bolt_sidecar.service

# build the project on the remote dev server
ssh shared@remotebeast "cd ~/bolt_sidecar && CC=clang ~/.cargo/bin/cargo build --release"
ssh shared@remotebeast "mv ~/bolt_sidecar/target/release/bolt-sidecar /usr/local/bin/bolt-sidecar || true"
ssh shared@remotebeast "cp -f ~/bolt_sidecar/bolt_sidecar.service /etc/systemd/system/bolt_sidecar.service"
ssh shared@remotebeast "sudo systemctl daemon-reload && sudo systemctl enable bolt_sidecar"
ssh shared@remotebeast "sudo systemctl restart bolt_sidecar"

echo "Deployed bolt_sidecar successfully"
Loading