Skip to content

Commit 8f9efb9

Browse files
committed
feat: check for unknown fields in config file
Error if an unknown field is found in a node's config file. This is helpful to catch errors in the config file.
1 parent 08abd6a commit 8f9efb9

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed

testnet/stacks-node/src/config.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ const INV_REWARD_CYCLES_TESTNET: u64 = 6;
8989
const DEFAULT_MIN_TIME_BETWEEN_BLOCKS_MS: u64 = 1000;
9090

9191
#[derive(Clone, Deserialize, Default, Debug)]
92+
#[serde(deny_unknown_fields)]
9293
pub struct ConfigFile {
9394
pub __path: Option<String>, // Only used for config file reloads
9495
pub burnchain: Option<BurnchainConfigFile>,
@@ -1318,6 +1319,7 @@ pub struct AffirmationOverride {
13181319
}
13191320

13201321
#[derive(Clone, Deserialize, Default, Debug)]
1322+
#[serde(deny_unknown_fields)]
13211323
pub struct BurnchainConfigFile {
13221324
pub chain: Option<String>,
13231325
pub mode: Option<String>,
@@ -2200,6 +2202,7 @@ impl Default for MinerConfig {
22002202
}
22012203

22022204
#[derive(Clone, Default, Deserialize, Debug)]
2205+
#[serde(deny_unknown_fields)]
22032206
pub struct ConnectionOptionsFile {
22042207
pub inbox_maxlen: Option<usize>,
22052208
pub outbox_maxlen: Option<usize>,
@@ -2383,6 +2386,7 @@ impl ConnectionOptionsFile {
23832386
}
23842387

23852388
#[derive(Clone, Deserialize, Default, Debug)]
2389+
#[serde(deny_unknown_fields)]
23862390
pub struct NodeConfigFile {
23872391
pub name: Option<String>,
23882392
pub seed: Option<String>,
@@ -2517,6 +2521,7 @@ impl NodeConfigFile {
25172521
}
25182522

25192523
#[derive(Clone, Deserialize, Default, Debug)]
2524+
#[serde(deny_unknown_fields)]
25202525
pub struct FeeEstimationConfigFile {
25212526
pub cost_estimator: Option<String>,
25222527
pub fee_estimator: Option<String>,
@@ -2528,6 +2533,7 @@ pub struct FeeEstimationConfigFile {
25282533
}
25292534

25302535
#[derive(Clone, Deserialize, Default, Debug)]
2536+
#[serde(deny_unknown_fields)]
25312537
pub struct MinerConfigFile {
25322538
pub first_attempt_time_ms: Option<u64>,
25332539
pub subsequent_attempt_time_ms: Option<u64>,
@@ -2670,6 +2676,7 @@ impl MinerConfigFile {
26702676
}
26712677
}
26722678
#[derive(Clone, Deserialize, Default, Debug)]
2679+
#[serde(deny_unknown_fields)]
26732680
pub struct AtlasConfigFile {
26742681
pub attachments_max_size: Option<u32>,
26752682
pub max_uninstantiated_attachments: Option<u32>,
@@ -2698,6 +2705,7 @@ impl AtlasConfigFile {
26982705
}
26992706

27002707
#[derive(Clone, Deserialize, Default, Debug, Hash, PartialEq, Eq, PartialOrd)]
2708+
#[serde(deny_unknown_fields)]
27012709
pub struct EventObserverConfigFile {
27022710
pub endpoint: String,
27032711
pub events_keys: Vec<String>,
@@ -2798,6 +2806,7 @@ pub struct InitialBalance {
27982806
}
27992807

28002808
#[derive(Clone, Deserialize, Default, Debug)]
2809+
#[serde(deny_unknown_fields)]
28012810
pub struct InitialBalanceFile {
28022811
pub address: String,
28032812
pub amount: u64,
@@ -2873,6 +2882,124 @@ mod tests {
28732882
assert!(Config::from_config_file(ConfigFile::from_str("").unwrap(), false).is_ok());
28742883
}
28752884

2885+
#[test]
2886+
fn test_deny_unknown_fields() {
2887+
{
2888+
let err = ConfigFile::from_str(
2889+
r#"
2890+
[node]
2891+
name = "test"
2892+
unknown_field = "test"
2893+
"#,
2894+
)
2895+
.unwrap_err();
2896+
assert!(err.starts_with("Invalid toml: unknown field `unknown_field`"));
2897+
}
2898+
2899+
{
2900+
let err = ConfigFile::from_str(
2901+
r#"
2902+
[burnchain]
2903+
chain_id = 0x00000500
2904+
unknown_field = "test"
2905+
chain = "bitcoin"
2906+
"#,
2907+
)
2908+
.unwrap_err();
2909+
assert!(err.starts_with("Invalid toml: unknown field `unknown_field`"));
2910+
}
2911+
2912+
{
2913+
let err = ConfigFile::from_str(
2914+
r#"
2915+
[node]
2916+
rpc_bind = "0.0.0.0:20443"
2917+
unknown_field = "test"
2918+
p2p_bind = "0.0.0.0:20444"
2919+
"#,
2920+
)
2921+
.unwrap_err();
2922+
assert!(err.starts_with("Invalid toml: unknown field `unknown_field`"));
2923+
}
2924+
2925+
{
2926+
let err = ConfigFile::from_str(
2927+
r#"
2928+
[[ustx_balance]]
2929+
address = "ST3AM1A56AK2C1XAFJ4115ZSV26EB49BVQ10MGCS0"
2930+
amount = 10000000000000000
2931+
unknown_field = "test"
2932+
"#,
2933+
)
2934+
.unwrap_err();
2935+
assert!(err.starts_with("Invalid toml: unknown field `unknown_field`"));
2936+
}
2937+
2938+
{
2939+
let err = ConfigFile::from_str(
2940+
r#"
2941+
[[events_observer]]
2942+
endpoint = "localhost:30000"
2943+
unknown_field = "test"
2944+
events_keys = ["stackerdb", "block_proposal", "burn_blocks"]
2945+
"#,
2946+
)
2947+
.unwrap_err();
2948+
assert!(err.starts_with("Invalid toml: unknown field `unknown_field`"));
2949+
}
2950+
2951+
{
2952+
let err = ConfigFile::from_str(
2953+
r#"
2954+
[connection_options]
2955+
inbox_maxlen = 100
2956+
outbox_maxlen = 200
2957+
unknown_field = "test"
2958+
"#,
2959+
)
2960+
.unwrap_err();
2961+
assert!(err.starts_with("Invalid toml: unknown field `unknown_field`"));
2962+
}
2963+
2964+
{
2965+
let err = ConfigFile::from_str(
2966+
r#"
2967+
[fee_estimation]
2968+
cost_estimator = "foo"
2969+
unknown_field = "test"
2970+
"#,
2971+
)
2972+
.unwrap_err();
2973+
assert!(err.starts_with("Invalid toml: unknown field `unknown_field`"));
2974+
}
2975+
2976+
{
2977+
let err = ConfigFile::from_str(
2978+
r#"
2979+
[miner]
2980+
first_attempt_time_ms = 180_000
2981+
unknown_field = "test"
2982+
subsequent_attempt_time_ms = 360_000
2983+
"#,
2984+
)
2985+
.unwrap_err();
2986+
println!("{}", err);
2987+
assert!(err.starts_with("Invalid toml: unknown field `unknown_field`"));
2988+
}
2989+
2990+
{
2991+
let err = ConfigFile::from_str(
2992+
r#"
2993+
[atlas]
2994+
attachments_max_size = 100
2995+
unknown_field = "test"
2996+
"#,
2997+
)
2998+
.unwrap_err();
2999+
assert!(err.starts_with("Invalid toml: unknown field `unknown_field`"));
3000+
}
3001+
}
3002+
28763003
#[test]
28773004
fn should_load_legacy_mstx_balances_toml() {
28783005
let config = ConfigFile::from_str(

0 commit comments

Comments
 (0)