Repository navigation
refactor: node mode two regimes - #5596
Open
martinconic wants to merge 29 commits into
Open
martinconic wants to merge 29 commits into
martinconic wants to merge 29 commits into
Conversation
Resolves a conflict in pkg/node/node.go where master (#5460) added a startup block-height verification guard for the postage listener, while this branch replaced the o.FullNodeMode bool with o.NodeMode == FullMode. Resolution keeps master's new guard and applies the NodeMode predicate to the subsequent batch-service start branch.
Resolved packaging yaml conflicts (bee, scoop, homebrew-amd64, homebrew-arm64): kept the mode-based section layout from this branch and added the new 'use-simd-hashing' option from master. The p2p-wss, nat-wss, autotls, and withdrawal-addresses-whitelist options master appended already exist in the reorganized Network/Payments sections, so master's duplicates were dropped.
Resolve conflicts from v2.8.0 (#5477): - cmd.go: keep node-mode flag and deprecated full-node path while adding master's chequebook-verification and chequebook-min-balance flags; keep chequebook-enable default of false. - node.go: take master's chain-enabled chequebook factory init (wallet ERC20 resolution); adapt new chequebook-verification check to use NodeMode == FullMode instead of the removed FullNodeMode field. - packaging/*.yaml: keep the section-organized layout and add the new chequebook-verification option.
Split resolveNodeMode into a legacy regime (node-mode unset) that reproduces the behaviour of releases before node-mode existed, and a mode-owned regime (node-mode set) where the mode supplies defaults for swap-enable, chequebook-enable and storage-incentives-enable. Legacy regime: restore the former true defaults of chequebook-enable and storage-incentives-enable when unset, infer the mode from full-node and blockchain-rpc-endpoint as before, apply no new validation, and log a deprecation warning naming the inferred mode and the removal release. This fixes upgraded configs that were broken in both directions: a light node with swap-enable only silently lost cheque settlement, and a config carrying the old chequebook-enable default without swap, or a bootnode with storage-incentives-enable false, refused to start. Mode-owned regime: full implies swap, chequebook and incentives unless explicitly disabled (bootnodes exempt, NewBee never starts them there), light and full require blockchain-rpc-endpoint, and options a mode cannot support are rejected only when explicitly enabled. node-mode=full is now sufficient on its own; validateFullMode and the full-node restore loop are removed. The node-mode flag default becomes empty so an unset value selects the legacy regime without relying on viper's IsSet semantics for pflag defaults. Tests cover both regimes, including a run against the real bound start flags.
… defaults Add BEE_NODE_MODE to the docker-compose environment passthrough and the env template, mark BEE_FULL_NODE deprecated, and correct the stale true defaults documented for BEE_CHEQUEBOOK_ENABLE and BEE_STORAGE_INCENTIVES_ENABLE. Document in the bee.yaml variants that full mode implies the swap, chequebook and incentives options and that an unset node-mode falls back to deprecated inference.
martinconic
marked this pull request as ready for review
September 3, 2026 13:02
sbackend123
approved these changes
Sep 3, 2026
| } | ||
| } | ||
| modeStr := c.config.GetString(optionNameNodeMode) | ||
| if modeStr == "" { |
Contributor
There was a problem hiding this comment.
Seems, this differs from the documented distinction based on whether node-mode is set. Should we use IsSet to distinguish an omitted value from an explicitly empty one?
| # BEE_CACHE_RETRIEVAL=true | ||
| ## enable chequebook (default true) | ||
| # BEE_CHEQUEBOOK_ENABLE=true | ||
| ## enable chequebook; requires swap; implied by BEE_NODE_MODE=full (default false) |
Contributor
There was a problem hiding this comment.
When BEE_NODE_MODE is unset, the legacy resolver restores chequebook-enable to true. Could we clarify that false applies only when BEE_NODE_MODE is explicitly set?
martinconic
changed the base branch from
refactor/node-mode-config
to
master
September 4, 2026 12:11
gacevicljubisa
requested changes
Sep 10, 2026
gacevicljubisa
left a comment
Member
There was a problem hiding this comment.
We should have backwards comaptibile bahviour, and only if new flag is explicitly set, then we may change it.
gacevicljubisa
approved these changes
Sep 23, 2026
21 of 22 tasks
…two-regimes # Conflicts: # packaging/bee.yaml # packaging/homebrew-amd64/bee.yaml # packaging/homebrew-arm64/bee.yaml # packaging/scoop/bee.yaml
Use the external test package, as the other tests in cmd/bee/cmd do, and expose the option names and resolver through export_test.go.
A full bootnode does not get swap implied, but chequebook-enable kept its flag default of true, so every full bootnode in the node-mode regime was rejected with "chequebook-enable requires swap-enable to be true". Set chequebook-enable and storage-incentives-enable to false when unset, as the light and ultra-light modes do, and cover the case with bound flags.
Resolve the node mode in the start command before the node is built in the background. A rejected configuration is now returned from RunE, so bee prints the error and exits with a non-zero status instead of logging it and exiting 0, and it is rejected before the keystore is unlocked.
An unset or unknown NodeMode enabled the chain backend while the API reported the node as ultra-light.
The exclusion matches nothing; golangci-lint reports no issues without it.
The examples showed ultra-light, but the default is unset, which infers the mode from the legacy options.
2b8338d forced chequebook-enable to false on every full bootnode where it was unset, so a bootnode with swap explicitly enabled ran swap without a chequebook. Replace the per-mode overrides with one rule after the mode switch: when chequebook-enable is not set explicitly it follows swap-enable. Outcomes through the bound start flags are otherwise unchanged, and bare-config resolution now agrees with them. Ultra-light now rejects an explicit chequebook-enable with a mode-specific error instead of pointing at swap-enable, and warns when a blockchain-rpc-endpoint is configured but ignored. Correct the bootnode comments, which claimed NewBee never starts swap there, and document the exemption in the packaged configs.
The deprecation warning told legacy operators to add node-mode, but doing only that changed what half of the legacy configs run: a full node without swap gained swap and a chequebook, and configs carrying the old defaults explicitly were rejected. The warning now lists the options to set and to remove so the node keeps its behavior, and notes where that is not possible (chequebook-verification without swap). A test applies the listed migration to every legacy combination of the mode options. Mode-dependent checks (bootnode must be full, reserve-capacity-doubling only on full nodes, swap needs a chain, chequebook-verification needs a full node with chequebook and chain) run in both regimes before the node is built, so they exit non-zero before the keystore is unlocked. Legacy configs are rejected exactly as before node-mode existed. With node-mode set, the value is matched case-insensitively and the blockchain-rpc-endpoint is trimmed, and a bootnode warns that storage-incentives-enable has no effect. The resolver tests run on the real start flags, so the legacy default-restoring loop is gone.
node-mode: light keeps swap opt-in, as light nodes had before node-mode. Without swap the node pays peers only through the free pseudosettle allowance, so it now logs that uploads and downloads are limited to it and how to exceed it. The packaged configs say the same.
An explicit swap-enable, chequebook-enable or storage-incentives-enable false on a full node is a deliberate choice, and the legacy migration suggests swap-enable=false itself, so logging it as a warning on every start gave operators a warning they could not resolve. Report it at Info, which stays visible at the default verbosity.
Beekeeper master configures nodes with full-node, which bee resolves through the legacy node mode. The beekeeper node-mode profiles merge after a bee release that knows node-mode.
martinconic
force-pushed
the
refactor/node-mode-two-regimes
branch
from
October 16, 2026 15:14
278f89d to
e289384
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist
Description
Closes #5172. Supersedes #5431, which this PR carries in full, and addresses the upgrade-path review @gacevicljubisa left there.
Bee's operational mode used to be implicit:
full-node: truegave a full node, otherwise ablockchain-rpc-endpointgave a light node, otherwise ultra-light. This PR adds an explicitnode-modeoption (full,light,ultra-light) and deprecatesfull-node. Existing configs keep working unchanged: which behaviour applies depends only on whethernode-modeis set.node-modeunset (legacy): behaves as master does today.chequebook-enableandstorage-incentives-enablekeep their default oftrue.NewBeestill gates them (chequebook on swap, incentives on full non-bootnode), so nothing starts that master would not start.v2.11.0, a constant instart.go), and the exact options to set and remove so the node keeps its behavior oncenode-modeis set. For example, a legacy full node without swap getsset=[node-mode=full, swap-enable=false] remove=[full-node]; a light node carryingstorage-incentives-enable: trueis told to remove it. Where behavior cannot be preserved (chequebook-verificationwithout swap), abehavior_changefield says what changes and what to choose.node-modeset: the mode owns the config.fullrequires an RPC endpoint and impliesswap-enable,chequebook-enableandstorage-incentives-enable. An explicitfalseis honored and logged at Info level, since it is a deliberate choice (the legacy migration may suggest it).NewBeenever runs the reserve or the incentives agent on a bootnode. Swap starts on a bootnode only whenswap-enableis set explicitly.lightrequires an RPC endpoint. Swap stays off unless set, as for light nodes on master: the base light node buys stamps and uploads and downloads within the free pseudosettle allowance, without a chequebook or funds at startup. When swap is off it logs, at Info, that uploads and downloads are limited to that allowance and thatswap-enable: truewith a funded chequebook exceeds it (the light node described in the docs).storage-incentives-enable: trueis rejected.ultra-lightrejectsswap-enable: true,chequebook-enable: trueandstorage-incentives-enable: true. A configured RPC endpoint is ignored, with a warning.chequebook-enablefollowsswap-enable. An explicitchequebook-enable: truewith swap off is rejected as a contradiction.full-nodeset alongsidenode-modeis ignored, with a warning.node-modevalue is matched case-insensitively and ignoring surrounding whitespace (FULLworks; a whitespace-only value is rejected). Surrounding whitespace inblockchain-rpc-endpointis trimmed, and a whitespace-only endpoint counts as unset.storage-incentives-enable: truestarts with a warning that the option has no effect there.Invalid configs exit with an error, in both regimes. Node mode is resolved and validated in the
startcommand before the node is built, so a rejected config printsError: …and exits with status 1, before the keystore is unlocked. Besides the per-mode rules above, these checks moved there fromNewBee(which keeps its copies for other callers): a bootnode must be full,reserve-capacity-doublingonly on full nodes, swap needs a chain, andchequebook-verificationneeds a full node with chequebook and chain. Previously these errors were only logged and the process exited 0. Other errors raised insideNewBee(for example an unreachable RPC endpoint) are unchanged.pkg/node:Options.FullNodeModeis replaced byOptions.NodeMode. The chain backend is enabled only forfullandlight, so an unset or unknown mode can no longer enable it./nodereports the configured mode.Flags:
node-modedefaults to empty, so unset selects the legacy behaviour without relying on viper'sIsSetsemantics for pflag defaults.full-nodeis marked deprecated.Packaging:
BEE_NODE_MODEadded to the docker-compose passthrough and the env template,BEE_FULL_NODEmarked deprecated, and the fourbee.yamlvariants reorganised into sections with a node-mode section documenting the modes, the bootnode exemption and the deprecated inference.Behaviour
Resolved values, as produced through the real
startflags:swap-enable: truechequebook-enable: true, no swapfull-node: true+ RPCfull-node+bootnode-mode+ RPC + incentivesfalsefull-node: true, no RPCswap-enable: true, no RPCreserve-capacity-doubling: 1full+ RPCfull+ RPC + incentivesfalsefull+ RPC + swapfalsefull+bootnode-mode+ RPCfull+bootnode-mode+ RPC + swaptruefull, no RPClight+ RPClight+ RPC + swaptruelight+ RPC + chequebooktruelight+bootnode-modeultra-lightultra-light+ RPCultra-light+ swap or chequebooktrueThe legacy rows match master: the same configs start with the same values, and the same configs are rejected, now earlier and with exit status 1. As on master,
NewBeestill starts the chequebook only when swap is on, and the incentives agent only on a full non-bootnode.Upgrade notes
node-mode: apply everything the deprecation warning lists undersetandremove, not only thenode-modeline. Addingnode-mode: fullalone to a legacy full node without swap turns on swap and deploys a chequebook (a gas transaction; startup waits while the wallet has no gas), and configs carrying the old defaults explicitly (storage-incentives-enable: trueon light/ultra-light,chequebook-enable: truewithout swap) are rejected.node-modemust drop it before downgrading.Restart=on-failure(systemd) or Dockeron-failure, a misconfigured node restarts instead of stopping.node-modeset,chequebook-enablefollowsswap-enable, so/nodereportschequebookEnabled: falsefor nodes without swap and/chequebook/*returns 403 on them. Legacy nodes without swap reporttruewhile no chequebook runs.Test plan
TestResolveNodeModecovers both behaviours case by case.TestResolveNodeModeWithBoundFlagsruns the resolver against the real boundstartflags, so the emptynode-modedefault and thetruedefaults of the sub-options are exercised as in production, including bootnodes and ultra-light rejections.TestResolveNodeModeWarningsasserts the warnings, including the migration'sset/removelists.TestResolveNodeModeTrimsRPCEndpointcovers endpoint trimming.TestIsChainEnabledcovers unset and unknown modes.TestLegacyMigrationPreservesBehaviorapplies the warning's migration to all 648 legacy combinations ofbootnode-mode× RPC ×full-node× swap/chequebook/incentives ×chequebook-verification: every config master accepts runs the same services after migration or carries abehavior_changenote, and the rejected combinations are exactly master's. Each new rule was also broken on purpose and caught by these tests.node-mode×bootnode-mode× RPC ×full-node× swap/chequebook/incentives (864 configs) resolved through the bound flags and compared across revisions; configs withoutnode-moderesolve as on master; the only legacy change across the follow-up fixes is that swap without a chain is rejected before the node is built.make lint(0 issues),go vet ./...,make buildandmake testpass.blockchain-rpckeys,BEE_*environment variables, flags) was exercised for the same rules, including empty, null, mixed-case and whitespace values.bee startsmoke tests against an unreachable RPC endpoint, legacy andnode-modeconfigs both reaching chain init; invalid configs exit 1 with the error printed; legacy rejections compared against a master build.local-dnscluster in fix(config): disable options rejected by bee in light and ultra-light… beekeeper#621 runs abee-legacynode (node-modeunset,full-node: true) next tonode-mode: fullnodes.BEEKEEPER_BRANCHis pinned to that branch to exercise both behaviours and is reset tomasterbefore merge. Beekeeper master still usesfull-node, which this PR handles as legacy; Add support for 'mantaray' manifest, and make it default #621 should merge only after a bee release that knowsnode-mode, since older bee rejects the unknown key.AI Disclosure