Skip to content
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
28 changes: 26 additions & 2 deletions cmd/ion-node/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,18 @@ func buildConfig(cCtx *cli.Context) (*config.Config, error) {
}
opts = append(opts, config.WithCheckpoint(height, hash))
}
return config.New(cCtx.String("network"), opts...)
cfg, err := config.New(cCtx.String("network"), opts...)
if err != nil {
return nil, err
}
// Sanity: warn (don't fail) if --genesis was overridden far below the network's
// ION-activation height — e.g. `--network mainnet --genesis 0` would scan ~667k
// pointless pre-ION blocks. A higher-than-default genesis is fine (skips old DIDs).
if def, derr := config.ProfileGenesisHeight(cfg.Network); derr == nil && cfg.GenesisHeight < def {
log.New(cCtx.Int("v")).Warn("genesis height is below the network's ION activation; scanning starts far too low and wastes time/bandwidth",
"network", cfg.Network, "genesisHeight", cfg.GenesisHeight, "expectedActivation", def)
}
return cfg, nil
}

// buildHeaderChain installs the trust anchors: the network's shipped checkpoints
Expand Down Expand Up @@ -435,10 +446,23 @@ func runConfig(cCtx *cli.Context) error {
if err != nil {
return err
}
// Surface the eclipse/fake-chain trust anchors so an operator can confirm them
// before launch: the min-chain-work floor (markSynced won't declare synced below
// it) and any augmenting checkpoint. The network's shipped checkpoints are always
// enforced in addition to these.
minChainWork := cfg.MinChainWork
if minChainWork == "" {
minChainWork = "unset"
}
checkpoint := "none"
if cfg.Checkpoint != nil {
checkpoint = fmt.Sprintf("%d:%s", cfg.Checkpoint.Height, cfg.Checkpoint.Hash)
}
log.New(cCtx.Int("v")).Info("resolved configuration",
"network", cfg.Network, "chainParams", cfg.Params.Name, "prefix", cfg.Prefix,
"genesisHeight", cfg.GenesisHeight, "confirmationDepth", cfg.ConfirmationDepth,
"maxReorgDepth", cfg.MaxReorgDepth, "targetOutbound", cfg.TargetOutbound, "dataDir", cfg.DataDir)
"maxReorgDepth", cfg.MaxReorgDepth, "targetOutbound", cfg.TargetOutbound,
"minChainWork", minChainWork, "extraCheckpoint", checkpoint, "dataDir", cfg.DataDir)
return nil
}

Expand Down
4 changes: 2 additions & 2 deletions docs/hardening-backlog.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ All items below survived an independent skeptic re-reading the cited code.
| 22 | ⚪ low | trivial | security | `keystore-open-no-perm-check` | ✅ done (#97) |
| 23 | ⚪ low | trivial | operational | `buildpsbt-missing-mainnet-gate` | open |
| 24 | ⚪ low | small | correctness | `scan-cid-shape-only-no-multihash-validation` | open |
| 25 | ⚪ low | trivial | operational | `config-command-hides-trust-anchors` | open |
| 25 | ⚪ low | trivial | operational | `config-command-hides-trust-anchors` | ✅ done (#107) |
| 26 | ⚪ low | trivial | correctness | `scan-zero-and-overcount-consume-block-cap-slot` | open |
| 27 | ⚪ low | medium | reliability | `observer-shutdown-blocks-on-cas-fetch` | open |
| 28 | ⚪ low | small | resource | `retrypending-loads-full-set-each-pass` | open |
Expand All @@ -65,7 +65,7 @@ All items below survived an independent skeptic re-reading the cited code.
| 35 | ⚪ low | small | test-gap | `walletstore-no-differential-fuzz` | open |
| 36 | ⚪ low | small | correctness | `headers-no-future-time-and-false-ban` | open |
| 37 | ⚪ low | small | test-gap | `cmd-ion-node-zero-tests` | open |
| 38 | ⚪ low | trivial | operational | `genesis-override-no-network-sanity-check` | open |
| 38 | ⚪ low | trivial | operational | `genesis-override-no-network-sanity-check` | ✅ done (#107) |
| 39 | ⚪ low | small | test-gap | `p2p-block-fetch-adversarial-untested` | open |
| 40 | ⚪ low | small | test-gap | `cas-cache-content-integrity-untested` | open |

Expand Down
11 changes: 11 additions & 0 deletions internal/config/profiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ func profileFor(network string) (*Config, error) {
}
}

// ProfileGenesisHeight returns a network's default (ION-activation) scan-start
// height, before any --genesis override. Used to warn when an override drops the
// start far below activation (a wasteful misconfiguration).
func ProfileGenesisHeight(network string) (int32, error) {
c, err := profileFor(network)
if err != nil {
return 0, err
}
return c.GenesisHeight, nil
}

// Networks returns the supported network profile names, sorted.
func Networks() []string {
n := []string{"mainnet", "testnet", "signet", "regtest", "simnet"}
Expand Down
26 changes: 26 additions & 0 deletions internal/config/profiles_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package config

import "testing"

func TestProfileGenesisHeight(t *testing.T) {
cases := map[string]int32{
"mainnet": 667000,
"testnet": 1764000,
"signet": 0,
"regtest": 0,
"simnet": 0,
}
for net, want := range cases {
got, err := ProfileGenesisHeight(net)
if err != nil {
t.Errorf("ProfileGenesisHeight(%q): %v", net, err)
continue
}
if got != want {
t.Errorf("ProfileGenesisHeight(%q) = %d, want %d", net, got, want)
}
}
if _, err := ProfileGenesisHeight("nope"); err == nil {
t.Error("ProfileGenesisHeight(unknown) should error")
}
}
Loading