Skip to content

Commit d9d058a

Browse files
committed
docker compose
1 parent 84c853b commit d9d058a

File tree

11 files changed

+330
-173
lines changed

11 files changed

+330
-173
lines changed

CHANGELOG.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,11 @@
3131
- [BREAKING] Modified `TransactionHeader` serialization to allow converting back into the native type after serialization ([#1759](https://github.com/0xMiden/node/issues/1759)).
3232
- Removed `chain_tip` requirement from mempool subscription request ([#1771](https://github.com/0xMiden/node/pull/1771)).
3333
- Moved bootstrap procedure to `miden-node validator bootstrap` command ([#1764](https://github.com/0xMiden/node/pull/1764)).
34+
- [BREAKING] Removed `bundled` command; each component is now started as a separate process. Added `ntx-builder` CLI subcommand. Added `docker-compose.yml` for local multi-process deployment ([#1765](https://github.com/0xMiden/node/pull/1765)).
3435

3536
### Fixes
3637

3738
- Fixed network monitor looping on stale wallet nonce after node restarts by re-syncing wallet state from RPC after repeated failures ([#1748](https://github.com/0xMiden/node/pull/1748)).
38-
- Fixed `bundled start` panicking due to duplicate `data_directory` clap argument name between `BundledCommand::Start` and `NtxBuilderConfig` ([#1732](https://github.com/0xMiden/node/pull/1732)).
39-
- Fixed `bundled bootstrap` requiring `--validator.key.hex` or `--validator.key.kms-id` despite a default key being configured ([#1732](https://github.com/0xMiden/node/pull/1732)).
4039
- Fixed incorrectly classifying private notes with the network attachment as network notes ([#1378](https://github.com/0xMiden/node/pull/1738)).
4140
- Fixed accept header version negotiation rejecting all pre-release versions; pre-release label matching is now lenient, accepting any numeric suffix within the same label (e.g. `alpha.3` accepts `alpha.1`) ([#1755](https://github.com/0xMiden/node/pull/1755)).
4241

Makefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,24 @@ install-network-monitor: ## Installs network monitor binary
127127

128128
# --- docker --------------------------------------------------------------------------------------
129129

130+
.PHONY: compose-genesis
131+
compose-genesis: ## Wipes node volumes and creates a fresh genesis block
132+
$(CONTAINER_RUNTIME) compose down --volumes --remove-orphans
133+
$(CONTAINER_RUNTIME) volume rm -f miden-node_genesis-data miden-node_store-data miden-node_validator-data miden-node_ntx-builder-data miden-node_accounts
134+
$(CONTAINER_RUNTIME) compose --profile genesis run --rm genesis
135+
136+
.PHONY: compose-up
137+
compose-up: ## Starts all node components via docker compose
138+
$(CONTAINER_RUNTIME) compose up -d
139+
140+
.PHONY: compose-down
141+
compose-down: ## Stops and removes all node containers via docker compose
142+
$(CONTAINER_RUNTIME) compose down
143+
144+
.PHONY: compose-logs
145+
compose-logs: ## Follows logs for all node components via docker compose
146+
$(CONTAINER_RUNTIME) compose logs -f
147+
130148
.PHONY: docker-build-node
131149
docker-build-node: ## Builds the Miden node using Docker (override with CONTAINER_RUNTIME=podman)
132150
@CREATED=$$(date) && \

bin/node/.env

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
# For more info use -h on the relevant commands:
2-
# miden-node bundled start -h
2+
# miden-node <component> start -h
33
MIDEN_NODE_BLOCK_PRODUCER_URL=
44
MIDEN_NODE_VALIDATOR_URL=
5-
MIDEN_NODE_NTX_BUILDER_URL=
65
MIDEN_NODE_BATCH_PROVER_URL=
76
MIDEN_NODE_BLOCK_PROVER_URL=
87
MIDEN_NODE_NTX_PROVER_URL=

bin/node/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ COPY . .
2828
RUN cargo build --release --locked --bin miden-node
2929

3030
# Base line runtime image with runtime dependencies installed.
31-
FROM debian:bullseye-slim AS runtime-base
31+
FROM debian:bookworm-slim AS runtime-base
3232
RUN apt-get update && \
3333
apt-get -y upgrade && \
3434
apt-get install -y --no-install-recommends sqlite3 \

bin/node/src/commands/mod.rs

Lines changed: 1 addition & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
use std::net::SocketAddr;
21
use std::num::NonZeroUsize;
3-
use std::path::{Path, PathBuf};
42
use std::time::Duration;
53

6-
use anyhow::Context;
74
use miden_node_block_producer::{
85
DEFAULT_BATCH_INTERVAL,
96
DEFAULT_BLOCK_INTERVAL,
@@ -14,11 +11,10 @@ use miden_node_utils::clap::duration_to_human_readable_string;
1411
use miden_node_validator::ValidatorSigner;
1512
use miden_protocol::crypto::dsa::ecdsa_k256_keccak::SecretKey;
1613
use miden_protocol::utils::Deserializable;
17-
use tokio::net::TcpListener;
1814
use url::Url;
1915

2016
pub mod block_producer;
21-
pub mod bundled;
17+
pub mod ntx_builder;
2218
pub mod rpc;
2319
pub mod store;
2420
pub mod validator;
@@ -97,113 +93,6 @@ impl ValidatorKey {
9793
}
9894
}
9995

100-
/// Configuration for the Validator component when run in the bundled mode.
101-
#[derive(clap::Args)]
102-
pub struct BundledValidatorConfig {
103-
/// Insecure, hex-encoded validator secret key for development and testing purposes.
104-
/// Only used when the Validator URL argument is not set.
105-
#[arg(
106-
long = "validator.key",
107-
env = ENV_VALIDATOR_KEY,
108-
value_name = "VALIDATOR_KEY",
109-
default_value = INSECURE_VALIDATOR_KEY_HEX
110-
)]
111-
validator_key: String,
112-
113-
/// The remote Validator's gRPC URL. If unset, will default to running a Validator
114-
/// in-process. If set, the insecure key argument is ignored.
115-
#[arg(long = "validator.url", env = ENV_VALIDATOR_URL, value_name = "URL")]
116-
validator_url: Option<Url>,
117-
}
118-
119-
impl BundledValidatorConfig {
120-
/// Converts the [`BundledValidatorConfig`] into a URL and an optional [`SocketAddr`].
121-
///
122-
/// If the `validator_url` is set, it returns the URL and `None` for the [`SocketAddr`].
123-
///
124-
/// If `validator_url` is not set, it binds to a random port on localhost, creates a URL,
125-
/// and returns the URL and the bound [`SocketAddr`].
126-
async fn to_addresses(&self) -> anyhow::Result<(Url, Option<SocketAddr>)> {
127-
if let Some(url) = &self.validator_url {
128-
Ok((url.clone(), None))
129-
} else {
130-
let socket_addr = TcpListener::bind("127.0.0.1:0")
131-
.await
132-
.context("Failed to bind to validator gRPC endpoint")?
133-
.local_addr()
134-
.context("Failed to retrieve the validator's gRPC address")?;
135-
let url = Url::parse(&format!("http://{socket_addr}"))
136-
.context("Failed to parse Validator URL")?;
137-
Ok((url, Some(socket_addr)))
138-
}
139-
}
140-
}
141-
142-
/// Configuration for the Network Transaction Builder component.
143-
#[derive(clap::Args)]
144-
pub struct NtxBuilderConfig {
145-
/// Disable spawning the network transaction builder.
146-
#[arg(long = "no-ntx-builder", default_value_t = false)]
147-
pub disabled: bool,
148-
149-
/// The remote transaction prover's gRPC url, used for the ntx builder. If unset,
150-
/// will default to running a prover in-process which is expensive.
151-
#[arg(long = "tx-prover.url", env = ENV_NTX_PROVER_URL, value_name = "URL")]
152-
pub tx_prover_url: Option<Url>,
153-
154-
/// Interval at which to run the network transaction builder's ticker.
155-
#[arg(
156-
long = "ntx-builder.interval",
157-
default_value = &duration_to_human_readable_string(DEFAULT_NTX_TICKER_INTERVAL),
158-
value_parser = humantime::parse_duration,
159-
value_name = "DURATION"
160-
)]
161-
pub ticker_interval: Duration,
162-
163-
/// Number of note scripts to cache locally.
164-
///
165-
/// Note scripts not in cache must first be retrieved from the store.
166-
#[arg(
167-
long = "ntx-builder.script-cache-size",
168-
env = ENV_NTX_SCRIPT_CACHE_SIZE,
169-
value_name = "NUM",
170-
default_value_t = DEFAULT_NTX_SCRIPT_CACHE_SIZE
171-
)]
172-
pub script_cache_size: NonZeroUsize,
173-
174-
/// Directory for the ntx-builder's persistent database.
175-
///
176-
/// If not set, defaults to the node's data directory.
177-
#[arg(long = "ntx-builder.data-directory", env = ENV_NTX_DATA_DIRECTORY, value_name = "DIR")]
178-
pub ntx_data_directory: Option<PathBuf>,
179-
}
180-
181-
impl NtxBuilderConfig {
182-
/// Converts this CLI config into the ntx-builder's internal config.
183-
///
184-
/// The `node_data_directory` is used as the default location for the ntx-builder's database
185-
/// if `--ntx-builder.data-directory` is not explicitly set.
186-
pub fn into_builder_config(
187-
self,
188-
store_url: Url,
189-
block_producer_url: Url,
190-
validator_url: Url,
191-
node_data_directory: &Path,
192-
) -> miden_node_ntx_builder::NtxBuilderConfig {
193-
let data_dir = self.ntx_data_directory.unwrap_or_else(|| node_data_directory.to_path_buf());
194-
let database_filepath = data_dir.join("ntx-builder.sqlite3");
195-
196-
miden_node_ntx_builder::NtxBuilderConfig::new(
197-
store_url,
198-
block_producer_url,
199-
validator_url,
200-
database_filepath,
201-
)
202-
.with_tx_prover_url(self.tx_prover_url)
203-
.with_script_cache_size(self.script_cache_size)
204-
}
205-
}
206-
20796
/// Configuration for the Block Producer component
20897
#[derive(clap::Args)]
20998
pub struct BlockProducerConfig {
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
use std::num::NonZeroUsize;
2+
use std::path::PathBuf;
3+
use std::time::Duration;
4+
5+
use anyhow::Context;
6+
use miden_node_utils::clap::duration_to_human_readable_string;
7+
use url::Url;
8+
9+
use super::{
10+
DEFAULT_NTX_SCRIPT_CACHE_SIZE,
11+
DEFAULT_NTX_TICKER_INTERVAL,
12+
ENV_BLOCK_PRODUCER_URL,
13+
ENV_ENABLE_OTEL,
14+
ENV_NTX_DATA_DIRECTORY,
15+
ENV_NTX_PROVER_URL,
16+
ENV_NTX_SCRIPT_CACHE_SIZE,
17+
ENV_STORE_NTX_BUILDER_URL,
18+
ENV_VALIDATOR_URL,
19+
};
20+
21+
#[derive(clap::Subcommand)]
22+
pub enum NtxBuilderCommand {
23+
/// Starts the network transaction builder component.
24+
Start {
25+
/// The store's ntx-builder service gRPC url.
26+
#[arg(long = "store.url", env = ENV_STORE_NTX_BUILDER_URL, value_name = "URL")]
27+
store_url: Url,
28+
29+
/// The block-producer's gRPC url.
30+
#[arg(long = "block-producer.url", env = ENV_BLOCK_PRODUCER_URL, value_name = "URL")]
31+
block_producer_url: Url,
32+
33+
/// The validator's gRPC url.
34+
#[arg(long = "validator.url", env = ENV_VALIDATOR_URL, value_name = "URL")]
35+
validator_url: Url,
36+
37+
/// The remote transaction prover's gRPC url. If unset, will default to running a
38+
/// prover in-process which is expensive.
39+
#[arg(long = "tx-prover.url", env = ENV_NTX_PROVER_URL, value_name = "URL")]
40+
tx_prover_url: Option<Url>,
41+
42+
/// Interval at which to run the network transaction builder's ticker.
43+
#[arg(
44+
long = "interval",
45+
default_value = &duration_to_human_readable_string(DEFAULT_NTX_TICKER_INTERVAL),
46+
value_parser = humantime::parse_duration,
47+
value_name = "DURATION"
48+
)]
49+
ticker_interval: Duration,
50+
51+
/// Number of note scripts to cache locally.
52+
///
53+
/// Note scripts not in cache must first be retrieved from the store.
54+
#[arg(
55+
long = "script-cache-size",
56+
env = ENV_NTX_SCRIPT_CACHE_SIZE,
57+
value_name = "NUM",
58+
default_value_t = DEFAULT_NTX_SCRIPT_CACHE_SIZE
59+
)]
60+
script_cache_size: NonZeroUsize,
61+
62+
/// Directory for the ntx-builder's persistent database.
63+
#[arg(long = "data-directory", env = ENV_NTX_DATA_DIRECTORY, value_name = "DIR")]
64+
data_directory: PathBuf,
65+
66+
/// Enables the exporting of traces for OpenTelemetry.
67+
///
68+
/// This can be further configured using environment variables as defined in the official
69+
/// OpenTelemetry documentation. See our operator manual for further details.
70+
#[arg(long = "enable-otel", default_value_t = false, env = ENV_ENABLE_OTEL, value_name = "BOOL")]
71+
enable_otel: bool,
72+
},
73+
}
74+
75+
impl NtxBuilderCommand {
76+
pub async fn handle(self) -> anyhow::Result<()> {
77+
let Self::Start {
78+
store_url,
79+
block_producer_url,
80+
validator_url,
81+
tx_prover_url,
82+
ticker_interval: _,
83+
script_cache_size,
84+
data_directory,
85+
enable_otel: _,
86+
} = self;
87+
88+
let database_filepath = data_directory.join("ntx-builder.sqlite3");
89+
90+
let config = miden_node_ntx_builder::NtxBuilderConfig::new(
91+
store_url,
92+
block_producer_url,
93+
validator_url,
94+
database_filepath,
95+
)
96+
.with_tx_prover_url(tx_prover_url)
97+
.with_script_cache_size(script_cache_size);
98+
99+
config
100+
.build()
101+
.await
102+
.context("failed to initialize ntx builder")?
103+
.run()
104+
.await
105+
.context("failed while running ntx builder component")
106+
}
107+
108+
pub fn is_open_telemetry_enabled(&self) -> bool {
109+
let Self::Start { enable_otel, .. } = self;
110+
*enable_otel
111+
}
112+
}

bin/node/src/commands/validator.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,7 @@ impl ValidatorCommand {
164164

165165
/// Bootstraps the genesis block: creates accounts, signs the block, and writes artifacts to
166166
/// disk.
167-
///
168-
/// This is extracted as a free function so it can be reused by the bundled bootstrap command.
169-
pub async fn bootstrap_genesis(
167+
async fn bootstrap_genesis(
170168
genesis_block_directory: &Path,
171169
accounts_directory: &Path,
172170
genesis_config: Option<&PathBuf>,

bin/node/src/main.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ pub struct Cli {
1717
pub command: Command,
1818
}
1919

20-
#[expect(clippy::large_enum_variant)]
2120
#[derive(Subcommand)]
2221
pub enum Command {
2322
/// Commands related to the node's store component.
@@ -32,15 +31,13 @@ pub enum Command {
3231
#[command(subcommand)]
3332
BlockProducer(commands::block_producer::BlockProducerCommand),
3433

35-
// Commands related to the node's validator component.
34+
/// Commands related to the node's validator component.
3635
#[command(subcommand)]
3736
Validator(commands::validator::ValidatorCommand),
3837

39-
/// Commands relevant to running all components in the same process.
40-
///
41-
/// This is the recommended way to run the node at the moment.
38+
/// Commands related to the node's network transaction builder component.
4239
#[command(subcommand)]
43-
Bundled(commands::bundled::BundledCommand),
40+
NtxBuilder(commands::ntx_builder::NtxBuilderCommand),
4441
}
4542

4643
impl Command {
@@ -53,7 +50,7 @@ impl Command {
5350
Command::Rpc(subcommand) => subcommand.is_open_telemetry_enabled(),
5451
Command::BlockProducer(subcommand) => subcommand.is_open_telemetry_enabled(),
5552
Command::Validator(subcommand) => subcommand.is_open_telemetry_enabled(),
56-
Command::Bundled(subcommand) => subcommand.is_open_telemetry_enabled(),
53+
Command::NtxBuilder(subcommand) => subcommand.is_open_telemetry_enabled(),
5754
} {
5855
OpenTelemetry::Enabled
5956
} else {
@@ -67,7 +64,7 @@ impl Command {
6764
Command::Store(store_command) => store_command.handle().await,
6865
Command::BlockProducer(block_producer_command) => block_producer_command.handle().await,
6966
Command::Validator(validator) => validator.handle().await,
70-
Command::Bundled(node) => node.handle().await,
67+
Command::NtxBuilder(ntx_builder) => ntx_builder.handle().await,
7168
}
7269
}
7370
}

0 commit comments

Comments
 (0)