Skip to main content

NodeCommand

Enum NodeCommand 

Source
pub enum NodeCommand {
Show 18 variants Health(HealthArgs), Status(StatusArgs), Lanes(LanesArgs), Slashes(SlashesArgs), Pools(PoolsArgs), Evict(EvictArgs), Reload(ReloadArgs), Drain(DrainArgs), Top(TopArgs), Register(RegisterArgs), Bond(BondArgs), Unbond(UnbondArgs), Deregister(DeregisterArgs), RotateKey(RotateKeyArgs), UpdateMultiaddrs(UpdateMultiaddrsArgs), UpdateRegion(UpdateRegionArgs), Lookup(LookupArgs), Doctor(Box<DoctorArgs>),
}
Expand description

Subcommands under decdn node.

Variants§

§

Health(HealthArgs)

Print a running node’s identity and process uptime.

§

Status(StatusArgs)

Print a snapshot of the running node’s DHT participation health via admin_v1_status (issue #741): Kademlia routing-table bucket fill rates, the network-wide last bucket-refresh time, the active-staker count, provider-record store utilization, and republish-scheduler depth. Lets operators diagnose cold-start or routing-table degradation without scraping Prometheus or reading logs.

§

Lanes(LanesArgs)

Print a live snapshot of the running node’s lanes via admin_v1_lanes (issue #749): per lane the outstanding accrued claim (micro-USDC), time since the last voucher, and whether the accrued claim has reached the configured redemption threshold. Lets operators spot lanes approaching settlement, stale lanes, or unusually high outstanding balances before they become a liquidity risk — without scraping metrics or reading logs. Same admin-URL resolution and timeout semantics as decdn node health.

§

Slashes(SlashesArgs)

Print every slash the node’s watcher has detected against its own operator via admin_v1_slashes (#1032, G-NODE-05): per slash the slashId, offense type, amount, evidence digest, block, and the 30-day appeal-window close time. Lets operators (or keeper scripts) notice a slash and file decdn appeal slash within the window without watching the chain directly. Same admin-URL resolution and timeout semantics as decdn node health.

§

Pools(PoolsArgs)

Print the running node’s buyer-side PaymentPool state via admin_v1_pools (#2078): every pool the node’s buy leg tracks, the deposit it believes each holds, and the per-lane amount it has already signed away to each provider. This is the node’s spending side — the mirror of decdn node lanes, which reports what it has earned.

The only way to read this state on a running node: the daemon holds an exclusive lock on its buyer.redb for its whole lifetime, so no command can open that file from disk while the node is up. decdn pool list manages a separate, client-owned store and says nothing about this one. Same admin-URL resolution and timeout semantics as decdn node health.

§

Evict(EvictArgs)

Forcibly remove a single blob from the local cache (issue #279). The removal is permanent: the node never serves or re-fetches the hash again. Useful for DMCA takedown and storage reclamation.

§

Reload(ReloadArgs)

Re-read the running node’s config file and apply hot-reloadable fields (issue #373). Equivalent to kill -HUP <pid> but goes through the loopback admin surface, so operator tooling that already speaks JSON-RPC doesn’t need to also know which PID to signal. observability.log_level, cache.pinned_hashes, security.*, the [content] denylist, and [load_shed] are reloadable; other fields are logged as ignored. The authoritative list is the module doc of the node’s runtime/reload.rs — when a section is added there, update this help text too. Both paths share the same internal mutex, so a concurrent SIGHUP and decdn node reload queue rather than race. Requires the node to have been started with decdn-node run --config <path> — without a path on disk there’s nothing to re-read.

§

Drain(DrainArgs)

Trigger graceful shutdown of the running node via admin_v1_drain (issue #244, adr/appendix-local-admin-http.md). Equivalent to kill -TERM <pid> but goes through the loopback admin surface, so operator tooling that already speaks JSON-RPC doesn’t need to also know which PID to signal. The runtime begins the same graceful shutdown sequence SIGTERM triggers (stops accept loops, waits for in-flight transfers, flushes cache).

Fire-and-forget semantics: this command returns drain_initiated=true as soon as the trigger is queued. The response does not mean shutdown is complete — it means the runtime has been asked to shut down, and the connection may close before the node fully exits because the admin server is one of the first surfaces to stop. Observe completion via process exit (systemd/K8s will notice) or by polling decdn node health until the connection is refused.

§

Top(TopArgs)

Render a live (every --interval-ms) view of node activity by scraping the running node’s /metrics HTTP endpoint (issue #275). Shows active streams, cache hit rate, and cache bytes returned — the operator-visible signal the issue calls “bytes served” maps to decdn_cache_bytes_returned_total until the network-side cdn/client/v1 egress counter (#317) lands.

§

Register(RegisterArgs)

Register this node on-chain via CapacityBond.registerNode (ADR 019 § Step 2.3). Loads the local iroh node key and Ethereum keystore, builds the EIP-712 bindingSignature and the ed25519 ownership signature locally, and submits the registration transaction. This is the only node subcommand that talks to the chain rather than a running node’s admin RPC.

Phase 2.1/2.2 (approve + bond + declareMbps) are a precondition: the contract reverts if the operator’s bond does not cover minBond / the declared-capacity curve. Pass --dry-run to print the parameters and signatures without submitting.

§

Bond(BondArgs)

Stake to a capacity tier on-chain via CapacityBond.bond + declareMbps (ADR 019 § Step 2.1–2.2). Idempotent: tops the active bond up to max(minBond, bondRequired(mbps)), approving and bonding only the shortfall, so re-running after a partial failure converges rather than over-bonding. Run this before decdn node register. Pass --dry-run to print the plan without submitting.

§

Unbond(UnbondArgs)

Lower the on-chain bond via CapacityBond.requestUnbond + unbond (ADR 026 § Capacity-bond curve) — the reverse of decdn node bond. State-aware: with no request in flight it declares the tier down (if needed) and starts the unbonding window; while one is maturing it reports the unlock time and exits non-zero; once matured it withdraws. Note that a request in flight makes the node INACTIVE for the whole window. Pass --dry-run to print the plan without submitting.

§

Deregister(DeregisterArgs)

Leave the active node set on-chain via CapacityBond.deregisterNode (ADR 003 § Node Registry) — the reverse of decdn node register, and the first leg of a full bond exit. Clears the declared capacity tier, which is what releases the bondRequired(declaredMbps) floor that decdn node unbond enforces.

This does NOT return the bond: it stays deposited and fully slashable. Follow with decdn node unbond --all to start the unbonding window, then re-run it after the window to withdraw. Pass --dry-run to print the plan without submitting.

§

RotateKey(RotateKeyArgs)

Rotate an operator key and keep the on-chain binding in step (adr/appendix-operator-key-rotation.md, #1034). --key chooses which key, because the two paths are not comparable in cost or effect.

--key iroh rebinds the wire node id through CapacityBond.bindNodeId. One transaction, no downtime beyond a restart, and the Ethereum address — with the bond, the declared tier, firstBondedAt, and every lane funded against this operator — is untouched. The old and new node ids swap slashability in the same block, so there is no window in which the operator cannot be slashed.

--key eth moves the whole on-chain identity, because no rebinding API exists for the address: deregister, wait out the full unbonding window, withdraw, then re-bond and re-register from a new address. firstBondedAt — and with it the governance age-ramp — resets. Like decdn node unbond, the phase is read from chain state rather than passed as a flag, so one command drives the whole window.

Neither path restarts the daemon: the iroh key is not hot-reloadable, so drain (decdn node drain), stop, rotate, restart stays the operator’s sequence. Pass --dry-run to print the plan — and, on the iroh path, both signatures — without submitting or touching any key file.

§

UpdateMultiaddrs(UpdateMultiaddrsArgs)

(Re)publish this node’s dialable QUIC addresses on-chain via CapacityBond.updateMultiaddrs (#1908). The one-command fix for a node that registered an empty multiaddr set (decdn node register with no --multiaddr) and is therefore stranded on the iroh relay path: it promotes direct addresses without a destructive deregister/re-register cycle (which register alone cannot do — a second register reverts NodeAlreadyRegistered).

Like the other on-chain node subcommands this talks to the chain, not a running node’s admin RPC, and signs with the operator Ethereum key. The node must be active; the contract’s guardrails — the maxMultiaddrSize byte ceiling and the multiaddrUpdateCooldown between updates — are pre-checked and reported before the send. Pass --dry-run to print the plan (packed size, ceiling, cooldown state) without submitting.

§

UpdateRegion(UpdateRegionArgs)

(Re)attest this node’s region on-chain via CapacityBond.updateRegion (ADR 030). The one-command fix for a node that registered the wrong regionHint (decdn node register --region) or whose operator has physically relocated: it corrects the region without a destructive deregister/re-register cycle (which register alone cannot do — a second register reverts NodeAlreadyRegistered).

Like the other on-chain node subcommands this talks to the chain, not a running node’s admin RPC, and signs with the operator Ethereum key. The region is validated as an ISO 3166-1 alpha-2 code CLI-side — the contract only length-checks and would otherwise store a garbage string. The node must be active; the contract’s regionStabilityWindow cooldown between updates is pre-checked and reported before the send. Pass --dry-run to print the plan (current region, new region, cooldown state) without submitting.

§

Lookup(LookupArgs)

Unpaid client-side discovery of active nodes via CapacityBond.getRegisteredNodes (#1481). Maps node-ids/regions to operator Ethereum addresses — the input decdn fetch --provider-address needs — without spending anything: it builds a signer-less read-only provider and never loads a keystore, unlike every other on-chain node subcommand above.

With neither --node-id nor --region, lists every active node. Pass --probe to additionally rank the (region-shortlisted) candidates by measured cdn/probe/v1 round-trip time; without it, candidates are listed with no RTT.

§

Doctor(Box<DoctorArgs>)

Diagnose config, on-disk state, disk budget, and reachability.

Trait Implementations§

Source§

impl Debug for NodeCommand

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl FromArgMatches for NodeCommand

Source§

fn from_arg_matches(__clap_arg_matches: &ArgMatches) -> Result<Self, Error>

Instantiate Self from ArgMatches, parsing the arguments as needed. Read more
Source§

fn from_arg_matches_mut( __clap_arg_matches: &mut ArgMatches, ) -> Result<Self, Error>

Instantiate Self from ArgMatches, parsing the arguments as needed. Read more
Source§

fn update_from_arg_matches( &mut self, __clap_arg_matches: &ArgMatches, ) -> Result<(), Error>

Assign values from ArgMatches to self.
Source§

fn update_from_arg_matches_mut<'b>( &mut self, __clap_arg_matches: &mut ArgMatches, ) -> Result<(), Error>

Assign values from ArgMatches to self.
Source§

impl Subcommand for NodeCommand

Source§

fn augment_subcommands<'b>(__clap_app: Command) -> Command

Append to Command so it can instantiate Self via FromArgMatches::from_arg_matches_mut Read more
Source§

fn augment_subcommands_for_update<'b>(__clap_app: Command) -> Command

Append to Command so it can instantiate self via FromArgMatches::update_from_arg_matches_mut Read more
Source§

fn has_subcommand(__clap_name: &str) -> bool

Test whether Self can parse a specific subcommand

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> MaybeSend for T
where T: Send,

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more