Skip to content

fix: remove implicit fallback behavior#2759

Open
cryptodj413 wants to merge 14 commits into
blinklabs-io:mainfrom
cryptodj413:fix/remove-implicit-fallback-behavior
Open

fix: remove implicit fallback behavior#2759
cryptodj413 wants to merge 14 commits into
blinklabs-io:mainfrom
cryptodj413:fix/remove-implicit-fallback-behavior

Conversation

@cryptodj413

@cryptodj413 cryptodj413 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Refs #1649


Summary by cubic

Removes silent fallback behavior across config loading and runtime, adds opt‑in strict modes for leader eligibility and slot clock, and improves diagnostics; config load is now isolated and --debug is registered early so validation logs are visible, refs #1649.

  • Bug Fixes

    • Config/CLI: strict YAML decoding rejects unknown fields; in wrapped mode only config, database, blob, metadata are allowed (and under database: only blob, metadata). Plugin config rejects unknown plugin names and keys; build‑tag‑only names (gcs, s3, mysql, postgres) are tolerated when not compiled. Storage mode is normalized. Config loading is isolated and early --debug registration ensures debug logs during load/validation.
    • Runtime validation: rejects bad logging.level/format, chainsync.strategy, mithril.backend, storageMode, out‑of‑range ports (incl. relayPort), malformed durations, and non‑positive shutdownTimeout, ledgerCatchupTimeout, and chainsync.stallTimeout (mithril.downloadIdleTimeout keeps its documented semantics). Validation runs after flags so valid CLI values can override bad YAML/env.
    • Networking/diagnostics: outbound dials warn if OutboundSourcePort cannot be resolved; unexpected event types are logged in UTxO RPC wait/watch, connection recycle, chain‑sync resync, and leios-notify/leios-fetch; unrecognized leios-notify messages are logged without closing the connection. Recovered panics include stack traces (chain selection, DB worker pool, Conway script‑purpose builder). Ledger view warns when bool‑only lookups hide DB errors; default blob/metadata plugin selection is debug‑logged.
  • Migration

    • New opt‑in strict modes: --strict-leader-eligibility and --strict-slot-clock (default false). Leave off during genesis bootstrap; enable to fail fast on persistent issues.
    • Use only supported values: logging level [debug, info, warn, error]; format [text, json]; chainsync.strategy (primary, parallel, round-robin); mithril.backend (v1, v2); storageMode (core, api); ports must be 0 or 1–65535. Durations must parse and be positive for shutdownTimeout, ledgerCatchupTimeout, and chainsync.stallTimeout (empty allowed).
    • Remove unknown YAML fields. In wrapped configs allow only config, database, blob, metadata at the top level; under database: allow only blob and metadata. Plugin configs must use documented keys; GCS no longer accepts project-id/prefix and S3 no longer accepts static credential keys (use Application Default Credentials / AWS default chain).

Written for commit 741f68a. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Improved logging for unexpected network and mempool events so issues are easier to diagnose.
    • Connection setup now handles invalid outbound source-port settings more gracefully and reports a clear warning.
    • Panic recovery across several workflows now includes stack traces, helping troubleshoot unexpected crashes.
    • Configuration loading is stricter: invalid or unknown settings are now rejected earlier, including logging, sync strategy, and backend values.
    • Default storage/plugin choices are now logged when automatically selected.

@cryptodj413
cryptodj413 requested a review from a team as a code owner July 6, 2026 17:22
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor
🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR covers config validation and warning/logging fallbacks, but it doesn't show the requested block/transaction validation propagation audit. Add the missing fail-fast changes for block/transaction processing and any remaining silent fallback paths, then include tests proving errors propagate.
✅ Passed checks (3 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed The changes stay within the fail-fast audit scope and mainly add validation, warnings, and tests.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main theme of the PR: replacing silent fallback behavior with explicit validation and warnings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/config/config.go (1)

949-992: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject unknown top-level siblings in wrapped config files internal/config/config.go:949-992 still decodes the root mapping leniently when config: is present, so a typo beside config: is dropped instead of failing fast. Validate top-level keys before entering the wrapped branch, or add coverage for this shape.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/config/config.go` around lines 949 - 992, Reject unknown top-level
siblings in wrapped config files by validating the root mapping before the
wrapped config path in the config loading logic. In the config unmarshalling
flow around tempConfig, strictUnmarshalConfig, and removeMappingKeys, make sure
any keys beside config/blob/metadata/database are rejected even when
tempCfg.Config is present, rather than being silently ignored. Add or adjust
coverage for the wrapped config case to confirm typos at the top level fail
fast.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@database/plugin/register.go`:
- Around line 105-127: Validate the plugin config keys in `register.go` before
mutating any destinations: in the `plugin.Options` handling, build the `known`
set and scan `pluginData` for unknown keys first, returning the `unknown config
key(s)` error before calling `option.ProcessConfig`. Then, only after validation
succeeds, run `option.ProcessConfig` for each option so `plugin.Options`,
`pluginData`, and `PluginTypeName(plugin.Type)` no longer allow partial
application when a typoed key is present.

---

Outside diff comments:
In `@internal/config/config.go`:
- Around line 949-992: Reject unknown top-level siblings in wrapped config files
by validating the root mapping before the wrapped config path in the config
loading logic. In the config unmarshalling flow around tempConfig,
strictUnmarshalConfig, and removeMappingKeys, make sure any keys beside
config/blob/metadata/database are rejected even when tempCfg.Config is present,
rather than being silently ignored. Add or adjust coverage for the wrapped
config case to confirm typos at the top level fail fast.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7cf01290-d90b-422a-958a-c2a24ccbe730

📥 Commits

Reviewing files that changed from the base of the PR and between b0694da and a241a24.

📒 Files selected for processing (24)
  • api/utxorpc/submit.go
  • chainselection/selector.go
  • connmanager/outbound.go
  • connmanager/outbound_test.go
  • database/database.go
  • database/default_plugin_log_test.go
  • database/plugin/process_config_test.go
  • database/plugin/register.go
  • dingo.yaml.example
  • internal/config/chainsync_strategy_test.go
  • internal/config/config.go
  • internal/config/config_test.go
  • internal/config/flags.go
  • internal/config/logging_test.go
  • internal/config/mithril_backend_test.go
  • internal/config/strict_unmarshal_test.go
  • internal/config/validate_after_flags_test.go
  • ledger/chainsync.go
  • ledger/eras/conway.go
  • ledger/state.go
  • ledger/state_test.go
  • ledger/verify_header.go
  • ouroboros/leios_merged_test.go
  • ouroboros/leiosnotify.go

Comment on lines +105 to 127
known := make(map[string]struct{}, len(plugin.Options))
for _, option := range plugin.Options {
known[option.Name] = struct{}{}
if err := option.ProcessConfig(pluginData); err != nil {
return err
}
}
var unknown []string
for key := range pluginData {
if _, ok := known[key]; !ok {
unknown = append(unknown, key)
}
}
if len(unknown) > 0 {
slices.Sort(unknown)
return fmt.Errorf(
"unknown config key(s) %v for %s plugin %q",
unknown,
PluginTypeName(plugin.Type),
plugin.Name,
)
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Validate unknown keys before applying known ones.

option.ProcessConfig (which mutates the plugin's Dest fields) runs inside the same loop that builds the known set, before the unknown-key scan executes. If a config block mixes valid and typo'd keys, the valid keys get applied to global/package state before the error is returned. Since this PR's goal is to avoid partial/implicit fallback behavior, validate all keys first, then apply.

🛠️ Proposed fix: validate before applying
 		known := make(map[string]struct{}, len(plugin.Options))
 		for _, option := range plugin.Options {
 			known[option.Name] = struct{}{}
-			if err := option.ProcessConfig(pluginData); err != nil {
-				return err
-			}
 		}
 		var unknown []string
 		for key := range pluginData {
 			if _, ok := known[key]; !ok {
 				unknown = append(unknown, key)
 			}
 		}
 		if len(unknown) > 0 {
 			slices.Sort(unknown)
 			return fmt.Errorf(
 				"unknown config key(s) %v for %s plugin %q",
 				unknown,
 				PluginTypeName(plugin.Type),
 				plugin.Name,
 			)
 		}
+		for _, option := range plugin.Options {
+			if err := option.ProcessConfig(pluginData); err != nil {
+				return err
+			}
+		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
known := make(map[string]struct{}, len(plugin.Options))
for _, option := range plugin.Options {
known[option.Name] = struct{}{}
if err := option.ProcessConfig(pluginData); err != nil {
return err
}
}
var unknown []string
for key := range pluginData {
if _, ok := known[key]; !ok {
unknown = append(unknown, key)
}
}
if len(unknown) > 0 {
slices.Sort(unknown)
return fmt.Errorf(
"unknown config key(s) %v for %s plugin %q",
unknown,
PluginTypeName(plugin.Type),
plugin.Name,
)
}
}
known := make(map[string]struct{}, len(plugin.Options))
for _, option := range plugin.Options {
known[option.Name] = struct{}{}
}
var unknown []string
for key := range pluginData {
if _, ok := known[key]; !ok {
unknown = append(unknown, key)
}
}
if len(unknown) > 0 {
slices.Sort(unknown)
return fmt.Errorf(
"unknown config key(s) %v for %s plugin %q",
unknown,
PluginTypeName(plugin.Type),
plugin.Name,
)
}
for _, option := range plugin.Options {
if err := option.ProcessConfig(pluginData); err != nil {
return err
}
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@database/plugin/register.go` around lines 105 - 127, Validate the plugin
config keys in `register.go` before mutating any destinations: in the
`plugin.Options` handling, build the `known` set and scan `pluginData` for
unknown keys first, returning the `unknown config key(s)` error before calling
`option.ProcessConfig`. Then, only after validation succeeds, run
`option.ProcessConfig` for each option so `plugin.Options`, `pluginData`, and
`PluginTypeName(plugin.Type)` no longer allow partial application when a typoed
key is present.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 24 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread database/plugin/register.go Outdated
Comment thread internal/config/chainsync_strategy_test.go Outdated
Comment thread database/plugin/register.go
Comment thread internal/config/config.go Outdated
Comment thread ledger/eras/conway.go
Comment thread api/utxorpc/submit.go

@wolf31o2 wolf31o2 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tightening several config paths and adding observability. I am requesting changes because the PR currently says Closes #1649, but it is only a partial pass and still has at least one strictness hole that preserves silent fallback behavior.

The blocking issue is wrapped YAML config: when config: is present, unknown top-level siblings are still decoded leniently and ignored. That means a typo like databse: can silently drop database settings and fall back to defaults. That conflicts directly with the config parsing part of #1649 and the PR description.

I would also avoid closing #1649 from this PR. There are still explicit warn-and-continue or fallback paths that need either better error handling, an operator-controlled strict mode, or a clearly scoped follow-up: database plugin defaulting, invalid outbound source-port fallback, leader eligibility skip cases, tx validation slot-clock fallback, best-effort Leios drops, and recovered chain-selection panics. Some of these may be legitimate operational tradeoffs, but then the PR should say Refs #1649 rather than Closes #1649 and should track the remaining work.

Validation I ran locally: go test ./... and make test both passed.

Comment thread internal/config/config.go
if tempCfg.Config != nil {
// Overlay config values onto existing defaults
configBytes, err := yaml.Marshal(tempCfg.Config)
if tempCfg.Config.Kind != 0 {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This branch still leaves the root document lenient when config: is present. yaml.Unmarshal(buf, &tempCfg) ignores unknown top-level siblings, and then this branch only strict-decodes tempCfg.Config. So a wrapped file with databse: instead of database: will load, silently drop the intended DB settings, and fall back to defaults. Please validate the root mapping in wrapped mode too, allowing only config, database, blob, and metadata, and add a regression test for an unknown top-level sibling next to a valid config: section.

Comment thread connmanager/outbound.go
)
dialer.LocalAddr = clientAddr
dialer.Control = socketControl
if resolveErr != nil {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now observable, but it is still a fallback: an invalid configured source port logs and then dials without source-port reuse. Since source-port reuse is required for peer sharing to be useful, I think this should fail during config validation/startup, or be gated behind an explicit tolerant mode. Logging and continuing is better than silent behavior, but it does not satisfy the fail-fast part of #1649.

Comment thread ledger/verify_header.go Outdated
// slot coefficient is logged and skipped rather than rejecting, to tolerate
// early-chain bootstrap states where the genesis snapshot is not yet written.
//
// Reviewed for issue #1649 (fail-fast audit) and intentionally kept as

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment makes sense as a risk note, but it also means #1649 is not complete here. If bootstrap needs a warn-and-continue window, we should distinguish expected bootstrap absence from unexpected post-bootstrap absence and fail after that boundary, with tests and DevNet coverage. Otherwise this PR should not close #1649.

Comment thread ledger/state.go Outdated
snapshotPParams := ls.currentPParams
snapshotPrevEraPParams := ls.prevEraPParams
ls.RUnlock()
// Reviewed for issue #1649 (fail-fast audit) and kept as graceful

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same concern here: this is still graceful degradation in transaction validation. Falling back to the snapshot tip slot may be a valid operational tradeoff, but it should either be controlled by an explicit strict/fail-fast option or called out as remaining #1649 work. As written, the PR documents that this fallback remains while claiming to close the audit.

Comment thread database/database.go
@@ -164,9 +164,21 @@ func New(
// Apply defaults for empty fields
if configCopy.BlobPlugin == "" {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still applies implicit plugin defaults when the caller passes an empty plugin name. The debug log helps, but #1649 specifically calls out database plugin initialization. If defaulting is intended, I would prefer it happen once in config defaulting with a clear source of truth; the database constructor should probably reject an empty plugin after config has been resolved, or at least this should be listed as remaining fallback work rather than part of a closed audit.

@cryptodj413

Copy link
Copy Markdown
Contributor Author

Let me replace the "Closes" with "Refs" and address these reviews. Thanks for your time.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 9 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread database/database.go

@wolf31o2 wolf31o2 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No-go for merge. The wrapped-config blocker was addressed, and the focused tests pass, but there are still two merge-blocking issues: a remaining silent fallback path under database:, and stale README plugin docs that now describe rejected config keys.

Validation run locally: git diff --check origin/main...HEAD; go test ./internal/config ./database/plugin ./database ./connmanager ./ledger ./chainselection ./api/utxorpc ./ouroboros.

Comment thread internal/config/config.go
if len(root.Content) > 0 {
removeMappingKeys(
root.Content[0],
[]string{"blob", "metadata", "database"},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still leaves a silent fallback hole one level lower. Because database is stripped before strict Config decoding, unknown children under database: are only seen by the lenient tempConfig decode. A typo like database.blbo: or database.metadtaa: is silently ignored and the node falls back to the default plugin settings, which is the behavior this PR is trying to remove. Please validate the database mapping itself only contains blob and metadata before stripping/processing it, and add coverage for typoed database children.

Comment thread dingo.yaml.example
prefix: ""
# Project and credentials are always resolved via Application
# Default Credentials. There is no plugin config option for
# project ID or a bucket key prefix.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removes the GCS project-id/prefix options from the example, but README.md still documents those as valid GCS options and still documents S3 static access-key-id/secret-access-key options. With the new strict plugin-key validation, following the README will now fail config load. Please update README.md to match the actual registered plugin options: GCS only bucket; S3 endpoint, bucket, region, and prefix, with credentials from the AWS default chain.

@cryptodj413
cryptodj413 requested review from a team as code owners July 14, 2026 08:57
@cryptodj413
cryptodj413 force-pushed the fix/remove-implicit-fallback-behavior branch from 81554af to 685b0ef Compare July 14, 2026 11:01

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 16 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="dingo.yaml.example">

<violation number="1" location="dingo.yaml.example:372">
P2: Genesis/bootstrap can still reject blocks despite this option being false: missing stake snapshots are returned as errors before `StrictLeaderEligibility` is consulted, rather than logged and skipped as this example says. Align the implementation with the documented fallback or narrow the comment to the total-stake and slot-coefficient cases that the flag actually gates.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread dingo.yaml.example Outdated
strictUtxoValidation: false

# Reject a block (instead of logging a warning and skipping the check) when
# the active stake snapshot or active slot coefficient needed to verify Praos

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Genesis/bootstrap can still reject blocks despite this option being false: missing stake snapshots are returned as errors before StrictLeaderEligibility is consulted, rather than logged and skipped as this example says. Align the implementation with the documented fallback or narrow the comment to the total-stake and slot-coefficient cases that the flag actually gates.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At dingo.yaml.example, line 372:

<comment>Genesis/bootstrap can still reject blocks despite this option being false: missing stake snapshots are returned as errors before `StrictLeaderEligibility` is consulted, rather than logged and skipped as this example says. Align the implementation with the documented fallback or narrow the comment to the total-stake and slot-coefficient cases that the flag actually gates.</comment>

<file context>
@@ -368,6 +368,21 @@ validateHistorical: false
 strictUtxoValidation: false
 
+# Reject a block (instead of logging a warning and skipping the check) when
+# the active stake snapshot or active slot coefficient needed to verify Praos
+# leader eligibility is unavailable. Leave disabled during genesis bootstrap,
+# where these are legitimately absent until the first stake snapshot is
</file context>

Comment thread internal/config/config.go Outdated
Comment thread ARCHITECTURE.md Outdated
Comment thread ledger/state.go Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 7 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread ARCHITECTURE.md Outdated
Comment thread internal/config/flags.go Outdated
@cryptodj413
cryptodj413 requested a review from wolf31o2 July 14, 2026 15:46

@wolf31o2 wolf31o2 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No-go for merge at the current head. The earlier wrapped-config and plugin-documentation blockers are fixed, and the focused tests plus conformance pass, but duration validation still preserves an implicit fallback path. Please reject non-positive timeout values where they are not explicitly supported and add YAML/env/CLI coverage for zero and negative durations. Because this touches header and transaction validation, DevNet validation remains required after the fix.

Comment thread internal/config/config.go Outdated
if d.value == "" {
continue
}
if _, err := time.ParseDuration(d.value); err != nil {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only checks whether the value parses. time.ParseDuration accepts "0s" and negative durations, so shutdownTimeout and chainsync.stallTimeout accept values that their consumers later silently replace with defaults (configuredShutdownTimeout falls back to 30s for <= 0, and chain-sync only applies a configured timeout when it is > 0). That retains the implicit fallback behavior this PR is intended to remove. Please validate the parsed duration semantically—requiring > 0 for these timeout fields unless a documented non-positive value has an intentional meaning—and add zero/negative tests across YAML, environment, and CLI inputs.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread internal/config/validate_runtime_config_test.go
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>
@cryptodj413
cryptodj413 force-pushed the fix/remove-implicit-fallback-behavior branch from c14ecc6 to 7c8996a Compare July 14, 2026 22:37
@cryptodj413
cryptodj413 requested a review from wolf31o2 July 14, 2026 23:00

@wolf31o2 wolf31o2 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes on the current head. The previous non-positive timeout finding is fixed correctly, the affected race-enabled package tests and conformance suite pass, and the branch merges cleanly with current main. Two items remain: semantic validation currently runs before higher-precedence CLI flags are applied, and the externally visible storage-plugin configuration behavior needs the required DATABASE.md documentation. DevNet should be rerun after the consensus-affecting changes are ready.

Comment thread internal/config/config.go Outdated
// --logging-level, --logging-format, --chainsync-strategy, or
// --mithril-backend flag reintroduce a value this check already
// rejects for YAML/env.
if err := validateRuntimeConfig(globalConfig); err != nil {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This semantic validation runs before ApplyFlags, so it violates the documented CLI > environment > YAML > defaults precedence whenever a lower layer contains a value that a valid CLI flag should replace. I reproduced this with:\n\nyaml\nshutdownTimeout: "0s"\n\n\nRunning dingo --config dingo.yaml --shutdown-timeout=30s load ... exits here with invalid shutdownTimeout "0s" before the valid CLI override is applied. The same ordering affects the other values checked by validateRuntimeConfig, such as logging level/format, ports, chainsync strategy, Mithril backend, and storage mode. Keep strict YAML shape/type decoding during load, but defer semantic validation until after flags have been applied in command startup; provide an explicit validation path for non-CLI callers. Please add a regression proving a valid CLI value overrides an invalid YAML/environment semantic value.

PluginTypeMetadata: {"mysql": {}, "postgres": {}},
}

// ProcessConfig applies plugin-specific config values from a parsed YAML

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes the externally visible configuration contract for every storage plugin: unknown plugin names/keys now fail startup, while optional build-tag-gated plugin sections are treated specially. Under the repository documentation rules, storage-plugin behavior changes require a DATABASE.md update; updating only README and dingo.yaml.example does not satisfy that bar. Please document the strict plugin-name/key behavior and the build-tag-gated exception in DATABASE.md. For example, database.blob.badger.buckit now fails instead of being ignored, whereas an optional GCS/S3 section cannot be fully key-validated when that plugin is not compiled into the binary.

Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 9 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread internal/config/validate_after_flags_test.go Outdated
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>
@cryptodj413
cryptodj413 requested a review from wolf31o2 July 16, 2026 09:36

@wolf31o2 wolf31o2 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No-go for merge at the current head. The branch merges cleanly with current main and the affected race-enabled package tests plus conformance pass, but the new semantic validation still violates the documented CLI precedence for the special --debug override. Please apply that override before logging-level validation and add regression coverage. DevNet remains required after the fix because this PR changes header and transaction validation.

Comment thread internal/config/config.go
cfg.RelayPort,
)
}
switch strings.ToLower(strings.TrimSpace(cfg.Logging.Level)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This rejects the configured logging level even when --debug is present, but cmd/dingo/main.go documents --debug as the highest-precedence override that forces debug level regardless of the configured value. I reproduced the precedence failure with DINGO_LOGGING_LEVEL=bogus go run ./cmd/dingo --debug version: startup exits here instead of running at debug level. Apply the --debug override before this semantic check (or otherwise exempt the superseded lower-priority level), and add an env/YAML + --debug regression test.

Comment thread internal/config/flags.go
// flag can override a semantically invalid YAML/env value instead of
// LoadConfig rejecting it beforehand. See ValidateRuntimeConfig's doc
// comment.
if err := ValidateRuntimeConfig(cfg); err != nil {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ApplyFlags has merged the flags declared in flagSpecs, but it has not applied the separate root-level --debug flag; that override is only consumed later by commonRun. Consequently this validation point is still too early for the effective logging level, despite the comment saying semantic validation occurs after CLI values are merged.

Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread internal/config/validate_after_flags_test.go
Comment thread internal/config/validate_after_flags_test.go
Signed-off-by: cryptodj413 <shinjirohara2@gmail.com>

@wolf31o2 wolf31o2 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No-go on the current head (741f68a0). I reproduced the PR against current main (ed882bb2) locally, and it no longer merges cleanly: internal/config/config.go conflicts with the new ApplyDefaults/Validate lifecycle, and ledger/state.go conflicts with the new loadStateSnapshots transaction-validation path. Please rebase and preserve both of those mainline refactors when integrating this work.

The two inline comments are also blocking because the new strict modes affect block acceptance and transaction validation, but only their configuration plumbing is tested. The full DevNet run passed with the defaults (false), so it does not exercise either enabled strict path.

The exact head is also not make golines clean; the target rewrites 22 changed files, including PR-added tests.

Before main advanced, the synthetic merge passed the affected race-enabled package tests, conformance, import boundaries, and the full DevNet suite including epoch-boundary consensus. The latest-base result cannot be tested until the conflicts are resolved. DATABASE.md and ARCHITECTURE.md were checked and their updates are appropriate, but should be rechecked after the rebase.

Comment thread ledger/verify_header.go
// Skip rather than reject.
// Skip rather than reject, unless the operator opted into
// strict leader eligibility.
if ls.config.StrictLeaderEligibility {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: add ledger-level behavioral coverage for this strict mode. The only tests that mention StrictLeaderEligibility verify default/YAML/CLI plumbing; none exercises block verification. Please cover both true and false for zero total active stake and for a missing/non-positive active-slot coefficient, asserting hard rejection only in strict mode. This changes block acceptance, and the DevNet run uses the default false, so it cannot catch regressions in this branch.

Comment thread ledger/state.go
// instead of validating it against a stale reference slot (issue #1649).
currentSlot, currentSlotErr := ls.CurrentSlot()
if currentSlotErr != nil {
if ls.config.StrictSlotClock {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: exercise the CurrentSlot error behavior with StrictSlotClock both enabled and disabled. Existing coverage only proves that the flag can be configured; it does not verify that strict mode rejects the transaction or that tolerant mode uses the snapshot-tip fallback (and records the fallback metric). This is a transaction-validation behavior change that the default DevNet configuration does not execute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants