@@ -170,6 +170,28 @@ pub struct ConfigFile {
170
170
pub __path : Option < String > , // Only used for config file reloads
171
171
pub burnchain : Option < BurnchainConfigFile > ,
172
172
pub node : Option < NodeConfigFile > ,
173
+ /// Represents an initial STX balance allocation for an address at genesis
174
+ /// for testing purposes.
175
+ ///
176
+ /// This struct is used to define pre-allocated STX balances that are credited to
177
+ /// specific addresses when the Stacks node first initializes its chainstate. These balances
178
+ /// are included in the genesis block and are immediately available for spending.
179
+ ///
180
+ /// **Configuration:**
181
+ /// Configured as a list `[[ustx_balance]]` in TOML.
182
+ ///
183
+ /// Example TOML entry:
184
+ /// ```toml
185
+ /// [[ustx_balance]]
186
+ /// address = "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2"
187
+ /// amount = 10000000000000000
188
+ /// ```
189
+ ///
190
+ /// This is intended strictly for testing purposes.
191
+ /// Attempting to specify initial balances if [`BurnchainConfig::mode`] is "mainnet" will
192
+ /// result in an invalid config error.
193
+ ///
194
+ /// Default: `None`
173
195
pub ustx_balance : Option < Vec < InitialBalanceFile > > ,
174
196
/// Deprecated: use `ustx_balance` instead
175
197
pub mstx_balance : Option < Vec < InitialBalanceFile > > ,
@@ -2468,13 +2490,24 @@ impl Default for NodeConfig {
2468
2490
impl NodeConfig {
2469
2491
/// Get a SocketAddr for this node's RPC endpoint which uses the loopback address
2470
2492
pub fn get_rpc_loopback ( & self ) -> Option < SocketAddr > {
2471
- let rpc_port = SocketAddr :: from_str ( & self . rpc_bind )
2472
- . map_err ( |e| {
2493
+ let rpc_port = self . rpc_bind_addr ( ) ?. port ( ) ;
2494
+ Some ( SocketAddr :: new ( Ipv4Addr :: LOCALHOST . into ( ) , rpc_port) )
2495
+ }
2496
+
2497
+ pub fn rpc_bind_addr ( & self ) -> Option < SocketAddr > {
2498
+ SocketAddr :: from_str ( & self . rpc_bind )
2499
+ . inspect_err ( |e| {
2473
2500
error ! ( "Could not parse node.rpc_bind configuration setting as SocketAddr: {e}" ) ;
2474
2501
} )
2475
- . ok ( ) ?
2476
- . port ( ) ;
2477
- Some ( SocketAddr :: new ( Ipv4Addr :: LOCALHOST . into ( ) , rpc_port) )
2502
+ . ok ( )
2503
+ }
2504
+
2505
+ pub fn p2p_bind_addr ( & self ) -> Option < SocketAddr > {
2506
+ SocketAddr :: from_str ( & self . p2p_bind )
2507
+ . inspect_err ( |e| {
2508
+ error ! ( "Could not parse node.rpc_bind configuration setting as SocketAddr: {e}" ) ;
2509
+ } )
2510
+ . ok ( )
2478
2511
}
2479
2512
2480
2513
pub fn add_signers_stackerdbs ( & mut self , is_mainnet : bool ) {
@@ -3784,12 +3817,97 @@ impl NodeConfigFile {
3784
3817
#[ derive( Clone , Deserialize , Default , Debug ) ]
3785
3818
#[ serde( deny_unknown_fields) ]
3786
3819
pub struct FeeEstimationConfigFile {
3820
+ /// Specifies the name of the cost estimator to use.
3821
+ /// This controls how the node estimates computational costs for transactions.
3822
+ ///
3823
+ /// Accepted values:
3824
+ /// - `"NaivePessimistic"`: The only currently supported cost estimator. This estimator
3825
+ /// tracks the highest observed costs for each operation type and uses the average
3826
+ /// of the top 10 values as its estimate, providing a conservative approach to
3827
+ /// cost estimation.
3828
+ ///
3829
+ /// If not specified, or if [`FeeEstimationConfigFile::disabled`] is `true`,
3830
+ /// the node will use the default cost estimator.
3831
+ ///
3832
+ /// Default: `"NaivePessimistic"`
3787
3833
pub cost_estimator : Option < String > ,
3834
+ /// Specifies the name of the fee estimator to use.
3835
+ /// This controls how the node calculates appropriate transaction fees based on costs.
3836
+ ///
3837
+ /// Accepted values:
3838
+ /// - `"ScalarFeeRate"`: Simple multiplier-based fee estimation that uses percentiles
3839
+ /// (5th, 50th, and 95th) of observed fee rates from recent blocks.
3840
+ /// - `"FuzzedWeightedMedianFeeRate"`: Fee estimation that adds controlled randomness
3841
+ /// to a weighted median rate calculator. This helps prevent fee optimization attacks
3842
+ /// by adding unpredictability to fee estimates while still maintaining accuracy.
3843
+ ///
3844
+ /// If not specified, or if [`FeeEstimationConfigFile::disabled`] is `true`,
3845
+ /// the node will use the default fee estimator.
3846
+ ///
3847
+ /// Default: `"ScalarFeeRate"`
3788
3848
pub fee_estimator : Option < String > ,
3849
+ /// Specifies the name of the cost metric to use.
3850
+ /// This controls how the node measures and compares transaction costs.
3851
+ ///
3852
+ /// Accepted values:
3853
+ /// - `"ProportionDotProduct"`: The only currently supported cost metric. This metric
3854
+ /// computes a weighted sum of cost dimensions (runtime, read/write counts, etc.)
3855
+ /// proportional to how much of the block limit they consume.
3856
+ ///
3857
+ /// If not specified, or if [`FeeEstimationConfigFile::disabled`] is `true`,
3858
+ /// the node will use the default cost metric.
3859
+ ///
3860
+ /// Default: `"ProportionDotProduct"`
3789
3861
pub cost_metric : Option < String > ,
3862
+ /// If `true`, all fee and cost estimation features are disabled.
3863
+ /// The node will use unit estimators and metrics, which effectively
3864
+ /// provide no actual estimation capabilities.
3865
+ ///
3866
+ /// When disabled, the node will:
3867
+ /// 1. Not track historical transaction costs or fee rates
3868
+ /// 2. Return simple unit values for costs for any transaction, regardless of its actual complexity
3869
+ /// 3. Be unable to provide meaningful fee estimates for API requests (always returns an error)
3870
+ /// 4. Consider only raw transaction fees (not fees per cost unit) when assembling blocks
3871
+ ///
3872
+ /// This setting takes precedence over individual estimator/metric configurations.
3873
+ /// When `true`, the values for [`FeeEstimationConfigFile::cost_estimator`],
3874
+ /// [`FeeEstimationConfigFile::fee_estimator`], and [`FeeEstimationConfigFile::cost_metric`]
3875
+ /// are ignored and treated as `None`.
3876
+ ///
3877
+ /// Default: `false`
3790
3878
pub disabled : Option < bool > ,
3879
+ /// If `true`, errors encountered during cost or fee estimation will be logged.
3880
+ /// This can help diagnose issues with the fee estimation subsystem.
3881
+ ///
3882
+ /// Default: `false`
3791
3883
pub log_error : Option < bool > ,
3884
+ /// Specifies the fraction of random noise to add if using the `FuzzedWeightedMedianFeeRate` fee estimator.
3885
+ /// This value should be in the range [0, 1], representing a percentage of the base fee rate.
3886
+ ///
3887
+ /// For example, with a value of 0.1 (10%), fee rate estimates will have random noise added
3888
+ /// within the range of ±10% of the original estimate. This randomization makes it difficult
3889
+ /// for users to precisely optimize their fees while still providing reasonable estimates.
3890
+ ///
3891
+ /// This setting is only relevant when [`FeeEstimationConfigFile::fee_estimator`] is set to
3892
+ /// `"FuzzedWeightedMedianFeeRate"`. It controls how much randomness is introduced in the
3893
+ /// fee estimation process to prevent fee optimization attacks.
3894
+ ///
3895
+ /// Default: `0.1` (10%)
3792
3896
pub fee_rate_fuzzer_fraction : Option < f64 > ,
3897
+ /// Specifies the window size for the [`WeightedMedianFeeRateEstimator`].
3898
+ /// This determines how many historical fee rate data points are considered
3899
+ /// when calculating the median fee rate.
3900
+ ///
3901
+ /// The window size controls how quickly the fee estimator responds to changing
3902
+ /// network conditions. A smaller window size (e.g., 5) makes the estimator more
3903
+ /// responsive to recent fee rate changes but potentially more volatile. A larger
3904
+ /// window size (e.g., 10) produces more stable estimates but may be slower to
3905
+ /// adapt to rapid network changes.
3906
+ ///
3907
+ /// This setting is primarily relevant when [`FeeEstimationConfigFile::fee_estimator`] is set to
3908
+ /// `"FuzzedWeightedMedianFeeRate"`, as it's used by the underlying [`WeightedMedianFeeRateEstimator`].
3909
+ ///
3910
+ /// Default: `5`
3793
3911
pub fee_rate_window_size : Option < u64 > ,
3794
3912
}
3795
3913
@@ -4047,9 +4165,118 @@ impl AtlasConfigFile {
4047
4165
#[ derive( Clone , Deserialize , Default , Debug , Hash , PartialEq , Eq , PartialOrd ) ]
4048
4166
#[ serde( deny_unknown_fields) ]
4049
4167
pub struct EventObserverConfigFile {
4168
+ /// URL endpoint (hostname and port) where event notifications will be sent via HTTP POST requests.
4169
+ ///
4170
+ /// The node will automatically prepend `http://` to this endpoint and append the
4171
+ /// specific event path (e.g., `/new_block`, `/new_mempool_tx`).
4172
+ /// Therefore, this value should be specified as `hostname:port` (e.g., "localhost:3700").
4173
+ ///
4174
+ /// **Do NOT include the `http://` scheme in this configuration value.**
4175
+ ///
4176
+ /// This should point to a service capable of receiving and processing Stacks event data.
4177
+ ///
4178
+ /// Default: No default. This field is required.
4050
4179
pub endpoint : String ,
4180
+ /// List of event types that this observer is configured to receive.
4181
+ ///
4182
+ /// For a more detailed documentation check the event-dispatcher docs in the `/docs` folder.
4183
+ ///
4184
+ /// Each string in the list specifies an event category or a specific event to subscribe to.
4185
+ /// For an observer to receive any notifications, this list must contain at least one valid key.
4186
+ /// Providing an invalid string that doesn't match any of the valid formats below will cause
4187
+ /// the node to panic on startup when parsing the configuration.
4188
+ ///
4189
+ /// All observers, regardless of their `events_keys` configuration, implicitly receive
4190
+ /// payloads on the `/attachments/new` endpoint.
4191
+ ///
4192
+ /// **Valid Event Keys:**
4193
+ ///
4194
+ /// - `"*"`: Subscribes to a broad set of common events.
4195
+ /// - **Events delivered to:**
4196
+ /// - `/new_block`: For blocks containing transactions that generate STX, FT, NFT, or smart contract events.
4197
+ /// - `/new_microblocks`: For all new microblock streams. **Note:** Only until epoch 2.5.
4198
+ /// - `/new_mempool_tx`: For new mempool transactions.
4199
+ /// - `/drop_mempool_tx`: For dropped mempool transactions.
4200
+ /// - `/new_burn_block`: For new burnchain blocks.
4201
+ /// - **Note:** This key does NOT by itself subscribe to `/stackerdb_chunks` or `/proposal_response`.
4202
+ ///
4203
+ /// - `"stx"`: Subscribes to STX token operation events (transfer, mint, burn, lock).
4204
+ /// - **Events delivered to:** `/new_block`, `/new_microblocks`.
4205
+ /// - **Payload details:** The "events" array in the delivered payloads will be filtered to include only STX-related events.
4206
+ ///
4207
+ /// - `"memtx"`: Subscribes to new and dropped mempool transaction events.
4208
+ /// - **Events delivered to:** `/new_mempool_tx`, `/drop_mempool_tx`.
4209
+ ///
4210
+ /// - `"burn_blocks"`: Subscribes to new burnchain block events.
4211
+ /// - **Events delivered to:** `/new_burn_block`.
4212
+ ///
4213
+ /// - `"microblocks"`: Subscribes to new microblock stream events.
4214
+ /// - **Events delivered to:** `/new_microblocks`.
4215
+ /// - **Payload details:**
4216
+ /// - The "transactions" field will contain all transactions from the microblocks.
4217
+ /// - The "events" field will contain STX, FT, NFT, or specific smart contract events
4218
+ /// *only if* this observer is also subscribed to those more specific event types
4219
+ /// (e.g., via `"stx"`, `"*"`, a specific contract event key, or a specific asset identifier key).
4220
+ /// - **Note:** Only until epoch 2.5.
4221
+ ///
4222
+ /// - `"stackerdb"`: Subscribes to StackerDB chunk update events.
4223
+ /// - **Events delivered to:** `/stackerdb_chunks`.
4224
+ ///
4225
+ /// - `"block_proposal"`: Subscribes to block proposal response events (for Nakamoto consensus).
4226
+ /// - **Events delivered to:** `/proposal_response`.
4227
+ ///
4228
+ /// - **Smart Contract Event**: Subscribes to a specific smart contract event.
4229
+ /// - **Format:** `"{contract_address}.{contract_name}::{event_name}"`
4230
+ /// (e.g., `ST0000000000000000000000000000000000000000.my-contract::my-custom-event`)
4231
+ /// - **Events delivered to:** `/new_block`, `/new_microblocks`.
4232
+ /// - **Payload details:** The "events" array in the delivered payloads will be filtered for this specific event.
4233
+ ///
4234
+ /// - **Asset Identifier for FT/NFT Events**: Subscribes to events (mint, burn, transfer) for a specific Fungible Token (FT) or Non-Fungible Token (NFT).
4235
+ /// - **Format:** `"{contract_address}.{contract_name}.{asset_name}"`
4236
+ /// (e.g., for an FT: `ST0000000000000000000000000000000000000000.my-ft-contract.my-fungible-token`)
4237
+ /// - **Events delivered to:** `/new_block`, `/new_microblocks`.
4238
+ /// - **Payload details:** The "events" array in the delivered payloads will be filtered for events related to the specified asset.
4239
+ ///
4240
+ /// **Configuration:**
4241
+ ///
4242
+ /// ```toml
4243
+ /// # Example events_keys in TOML configuration:
4244
+ /// events_keys = [
4245
+ /// "burn_blocks",
4246
+ /// "memtx",
4247
+ /// "ST0000000000000000000000000000000000000000.my-contract::my-custom-event", # Smart contract event
4248
+ /// "ST0000000000000000000000000000000000000000.token-contract.my-ft" # Fungible token asset event
4249
+ /// ]
4250
+ /// ```
4251
+ ///
4252
+ /// Default: No default. This field is required.
4051
4253
pub events_keys : Vec < String > ,
4254
+ /// Maximum duration (in milliseconds) to wait for the observer endpoint to respond.
4255
+ ///
4256
+ /// When the node sends an event notification to this observer, it will wait at most this long
4257
+ /// for a successful HTTP response (status code 200) before considering the request timed out.
4258
+ /// If a timeout occurs and retries are enabled (see [`EventObserverConfig::disable_retries`]),
4259
+ /// the request will be attempted again according to the retry strategy.
4260
+ ///
4261
+ /// Default: `1_000` ms (1 second).
4052
4262
pub timeout_ms : Option < u64 > ,
4263
+ /// Controls whether the node should retry sending event notifications if delivery fails or times out.
4264
+ ///
4265
+ /// - If `false` (default): The node will attempt to deliver event notifications persistently.
4266
+ /// If an attempt fails (due to network error, timeout, or a non-200 HTTP response), the event
4267
+ /// payload is saved and retried indefinitely. This ensures that all events will eventually be
4268
+ /// delivered. However, this can cause the node's block processing to stall if an observer is
4269
+ /// down, or indefinitely fails to process the event.
4270
+ ///
4271
+ /// - If `true`: The node will make only a single attempt to deliver each event notification.
4272
+ /// If this single attempt fails for any reason, the event is discarded, and no further retries
4273
+ /// will be made for that specific event.
4274
+ ///
4275
+ /// **Warning:** Setting this to `true` can lead to missed events if the observer endpoint is
4276
+ /// temporarily unavailable or experiences issues. This setting should only be used for observers
4277
+ /// where completeness of the event history is not critical.
4278
+ ///
4279
+ /// Default: `false` (retries are enabled).
4053
4280
pub disable_retries : Option < bool > ,
4054
4281
}
4055
4282
@@ -4152,7 +4379,15 @@ pub struct InitialBalance {
4152
4379
#[ derive( Clone , Deserialize , Default , Debug ) ]
4153
4380
#[ serde( deny_unknown_fields) ]
4154
4381
pub struct InitialBalanceFile {
4382
+ /// The Stacks address to receive the initial STX balance.
4383
+ /// Must be a valid "non-mainnet" Stacks address (e.g., "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2").
4384
+ ///
4385
+ /// Default: No default. This field is required.
4155
4386
pub address : String ,
4387
+ /// The amount of microSTX to allocate to the address at node startup.
4388
+ /// 1 STX = 1_000_000 microSTX.
4389
+ ///
4390
+ /// Default: No default. This field is required.
4156
4391
pub amount : u64 ,
4157
4392
}
4158
4393
0 commit comments