Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Governance Gossip Handler

File: kinetic-node/src/gossip.rs Crate: kinetic-node | Stage: 12


What Is This?

handle_kinetic_governance_gossip() is called every time a GOSSIP_TOPIC_GOVERNANCE message arrives over P2P. It is the only place in kinetic-node that writes to the application state.

The daemon also handles governance gossip in kinetic-daemon/src/services/gossip.rs. The difference: the node version also writes NameRecord::Premium and NameRecord::PremiumRevoked entries directly into the Sled storage, making the change immediately queryable via DHT.


How It Works

Parse and verify

#![allow(unused)]
fn main() {
serde_json::from_slice::<SignedGovernanceMessage>(payload)
process_governance_message(&mut state, &signed_msg)
}

-> See: kinetic-node/src/gossip.rs — Lines 18–24

serde_json::from_slice::<SignedGovernanceMessage>(payload) — if this fails (invalid JSON, wrong schema), the function returns silently. No panic, no error propagation.

process_governance_message(&mut state, &signed_msg) — validates the message signatures against the governance keys in GLOBAL_GOVERNANCE_STATE. The global mutex is acquired, the state is mutated, then immediately cloned and the mutex is released before any disk I/O. This keeps the critical section minimal.


Three outcomes

#![allow(unused)]
fn main() {
GovernanceEffect::PremiumNameGranted
GovernanceEffect::PremiumNameRevoked
NameRecord::Premium
<DB_PREFIX_REVEAL><name>
tokio::task::spawn_blocking()
}

-> See: kinetic-node/src/gossip.rs — Lines 27–80

Ok(Some(effect)) — the message was valid and produced a state change:

  • GovernanceEffect::PremiumNameGranted { name, target_pubkey } → writes a NameRecord::Premium to Sled under the key <DB_PREFIX_REVEAL><name>. This makes the premium name immediately resolvable via DHT without waiting for a user to register it.
  • GovernanceEffect::PremiumNameRevoked { name } → deletes the NameRecord::Premium from Sled. The name becomes unresolvable.
  • Any other effect → no storage write.
  • Saves updated GovernanceState to disk via tokio::task::spawn_blocking() (disk I/O offloaded from the async executor).

Ok(None) — message was valid but produced no effect (e.g., already applied):

  • Saves state to disk anyway (to update timestamps/sequence numbers).

Err(e) — message was rejected (bad signature, replay attack, wrong sequence):

  • Logs at DEBUG level only. No storage write, no disk save.

Why spawn_blocking for disk saves?

#![allow(unused)]
fn main() {
GovernanceState::save_to_disk()
std::fs::write()
spawn_blocking
}

GovernanceState::save_to_disk() calls std::fs::write(), which blocks the OS thread.

Important

Inside a Tokio async context, blocking the executor thread stalls all other tasks. spawn_blocking moves the disk write to Tokio’s blocking thread pool, keeping the async executor free.


Tests

  • test_handle_invalid_json_payload — garbage bytes → no panic.
  • test_handle_invalid_signature — valid JSON, empty signatures → rejected gracefully.
  • test_handle_wrong_json_schema{"hello":"world"} → fails JSON parse of SignedGovernanceMessage.
  • test_handle_massive_payload — 1MB of [] → serde rejects it, no OOM.
  • test_handle_unexpected_fields — extra JSON fields → parsed with #[serde(deny_unknown_fields)] behavior.
  • test_save_to_disk_failure — lockpath is a directory → save_to_disk returns Err, no panic.
  • Fuzz: doesnt_crash_on_random_gossip_bytes — proptest random bytes → never panics.

-> See: kinetic-node/src/gossip.rs — Lines 87–197


Quick Reference

EventStorage Effect
PremiumNameGrantedWrite NameRecord::Premium to Sled
PremiumNameRevokedDelete NameRecord::Premium from Sled
Other governance effectNo storage write
Invalid signatureIgnored, DEBUG log
Bad JSONIgnored, DEBUG log