pub struct StagedNodeKey { /* private fields */ }Expand description
A freshly-generated node key written to a temp file in data_dir, not yet
committed to node.secret.
Staging (generate + write the temp) is separated from committing
(archive-old + rename) so a multi-file rotation can generate all key
material before touching any canonical file — a failure while generating the
second secret then leaves the first untouched rather than half-rotated
(#844). Produced by stage_node_key; finished with Self::commit.
Dropping a StagedNodeKey without committing removes the temp file, so an
abandoned stage never litters data_dir.
Implementations§
Source§impl StagedNodeKey
impl StagedNodeKey
Sourcepub fn public(&self) -> PublicKey
pub fn public(&self) -> PublicKey
The public key of the staged secret, for logging the node id before the commit lands.
Sourcepub fn sign(&self, msg: &[u8]) -> Signature
pub fn sign(&self, msg: &[u8]) -> Signature
Sign msg with the staged secret, without committing it.
decdn node rotate-key needs this: CapacityBond.bindNodeId demands an
ed25519 ownership proof from the key being bound, and that proof has to
exist before the transaction is submitted — while committing
node.secret has to happen after it confirms, or a reverted bind
would leave the daemon serving under an unbound identity. Signing from
the stage is what lets those two orders coexist.
The secret itself stays unreachable: this is deliberately a signing
oracle rather than a secret() accessor, so a staged key cannot be
copied out and persisted somewhere the archive-on-commit discipline
does not cover.
Sourcepub fn commit(&mut self) -> Result<Option<PathBuf>>
pub fn commit(&mut self) -> Result<Option<PathBuf>>
Commit the staged key: archive any existing node.secret (so the
operator key-rotation runbook keeps the prior material, mirroring the
no-stage path) and atomically rename the temp into place.
Returns the archive path if a prior key was moved aside, or None when
there was nothing to archive (fresh install).
Takes &mut self rather than self so a failed commit does not
destroy the key. Consuming self meant the ? below dropped the
stage with committed == false, and Drop deleted the temp — on a
caller path (decdn node rotate-key) that only reaches this call after
proving on-chain that the binding moved to this key. The caller must
stay able to Self::keep it instead. The cost is that a caller can
now observe a committed stage; commit is idempotent-safe in that a
second call would simply fail on the already-renamed temp.
§Errors
Returns an error if archiving the prior key or the install rename fails.
The commit is fail-safe via install_staged: if the install rename
fails after the prior key was archived, the archive is restored
(best-effort) so the old key stays live, and the error states whether the
restore succeeded or node.secret is now missing. On error committed
stays false, so the caller may still Self::keep the staged key —
and if it does not, Drop reclaims the temp.
Sourcepub fn keep(self) -> Result<PathBuf>
pub fn keep(self) -> Result<PathBuf>
Preserve the staged key without installing it, at
<data_dir>/node.secret.pending.<node_id>. Returns the path it landed at.
The third outcome, between Self::commit and the Drop that discards
an abandoned stage. It exists for one situation, reached three ways: a
key-rotation transaction may have taken effect, but the caller cannot
confirm the binding moved — the receipt could not be read at all, or it
mined carrying no matching NodeIdBound, or it mined and the install of
the confirmed key then failed. Whether the chain now names this key is
unknown in the first two, and known in the third — where the key is
even more valuable. Discarding the secret there is unrecoverable — if the
transaction did land, the operator is bound to an identity whose private
key no longer exists anywhere, and the daemon keeps serving under a key
nothing binds. Installing it is equally wrong, because the transaction
may instead have failed.
So the key is parked under a name that is deliberately not
node.secret: no daemon will load it (load_or_create reads exactly
<data_dir>/node.secret), and the operator can install it once they have
checked whether the transaction confirmed.
§Errors
Returns an error if the destination has no parent directory, or if the
rename fails. In both cases the staged temp is deliberately left in
place and its path is named in the error, rather than being reclaimed by
Drop: this is only ever called when the key may already be bound
on-chain, so an awkwardly-named surviving file beats an unrecoverable
identity. The caller is expected to print that path.
Trait Implementations§
Source§impl Debug for StagedNodeKey
impl Debug for StagedNodeKey
Source§impl Drop for StagedNodeKey
impl Drop for StagedNodeKey
Auto Trait Implementations§
impl Freeze for StagedNodeKey
impl RefUnwindSafe for StagedNodeKey
impl Send for StagedNodeKey
impl Sync for StagedNodeKey
impl Unpin for StagedNodeKey
impl UnsafeUnpin for StagedNodeKey
impl UnwindSafe for StagedNodeKey
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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