Event Loop Utilities and XOR Tie-Breaker
Crate: kinetic-network Stage: 8 Reading time: 55 minutes Depends on: types/01_overview.md, types/04_reveal.md, vdf/01_overview.md, kid/01_overview.md
What Is This?
This file provides the essential utility structures and foundational functions that power the asynchronous NetworkEventLoop inside the Kinetic network. It acts as the critical glue code that holds the complex, distributed networking logic together. Specifically, it includes the state-tracking structures (PendingGet, PendingPut, PendingQuorum) that bridge the gap between asynchronous DHT (Distributed Hash Table) queries and the synchronous-looking code that requests them.
Furthermore, it contains the cross-platform execution wrappers for spawning background tasks, ensuring the codebase compiles and runs identically on native servers and WebAssembly (WASM) browser clients. It also includes the multiaddress validation logic to prevent local network IP pollution from corrupting the public routing table, which is a common vulnerability in decentralized networks.
Most importantly, this file implements the xor_tie_breaker—the deterministic conflict resolution algorithm used when multiple peers claim ownership of the exact same Kademlia DHT key. This tie-breaker is the core consensus mechanism for the Kinetic naming system, dictating how the network agrees on who truly owns a name when multiple valid cryptographic proofs are presented to it simultaneously.
Without this file, the network would have no way to process asynchronous responses, would crash on WASM targets, would be poisoned by private IPs, and would fork into a million different states because it couldn’t agree on name ownership.
Why Kinetic Needs This
To truly understand why these utilities are necessary, you have to look at the hostile, chaotic, and asynchronous environment of a decentralized P2P network.
The Asynchronous Chaos of the Kademlia DHT
The Kademlia Distributed Hash Table is inherently asynchronous and distributed. When a node asks the network for a record (like searching for a user’s IP address or searching for the owner of a .kin domain name), it doesn’t just query a central database and wait for a single immediate answer. It asks multiple nodes across the globe simultaneously. Their responses will then trickle in over time as discrete, unpredictable events over the network socket.
Kinetic needs a structured, reliable way to track these inflight requests. If a user queries the network for a Reveal record, the system needs a way to “park” that user’s specific request in memory, go out to the network, collect the asynchronous responses over the next few seconds, and then specifically wake up the user’s parked request to hand them the final, accumulated result. The Pending* tracking structures solve this exact problem, preventing network responses from getting lost in the void and ensuring the original caller gets their data.
The WebAssembly Execution Gap and Single-Threaded Constraints
Kinetic is designed to run everywhere—from powerful native server nodes using the Tokio async runtime to lightweight browser environments using WebAssembly (WASM). These environments have vastly different execution models that are fundamentally incompatible out of the box. Native Rust uses OS-level threads to handle blocking operations and background tasks efficiently. WASM, however, runs in a single-threaded JavaScript event loop environment where blocking operations will freeze the entire browser tab and crash the user experience.
Kinetic needs abstraction functions (spawn and spawn_blocking) to hide these deep platform differences from the rest of the network logic. By using these utility wrappers, developers can write network logic once, and the compiler will automatically select the correct concurrency model based on the target architecture, ensuring safety and performance across both targets.
The Threat of Routing Pollution and Local Traps
A decentralized network is vulnerable to accidental or malicious IP pollution. Nodes might misconfigure their routers or intentionally act maliciously by advertising their local, private IP addresses (like 192.168.1.5, 10.0.0.1, or 127.0.0.1) to the global DHT. If other honest nodes try to connect to these addresses, they will either fail instantly, wasting network bandwidth, or worse, they will unknowingly attempt to connect to unintended private devices on their own local area network (LAN), creating a severe security vulnerability known as Server-Side Request Forgery (SSRF).
Kinetic needs a strict, automated, and ruthless filter to ensure only globally routable, public addresses are accepted into the routing tables, dropping anything that looks suspicious or reserved.
The Fundamental Problem of Decentralized Truth
Finally, and most crucially, the Kademlia DHT does not enforce data uniqueness natively. It is just a dumb storage layer. The network relies on Verifiable Delay Functions (VDFs) to prove that someone spent the required CPU time to claim a name. But what happens if two miners start computing a VDF for the exact same name at the exact same time, using the exact same drand randomness, and both finish and publish to the DHT simultaneously?
The DHT will now hold multiple conflicting Reveal records for the exact same key. The network needs a trustless, deterministic, and mathematical way to agree on who the true winner is. If different nodes pick different winners based on when they received the packet, the network splinters into forks. The xor_tie_breaker provides this objective truth, ensuring all honest nodes reach the exact same conclusion independently without needing to communicate with each other.
How It Works
The utilities in this file can be conceptually broken down into four distinct categories: Pending Requests, Task Spawning, Address Routing, and Conflict Resolution. We will examine the deep mechanics of each category.
1. Managing Asynchronous State Flow
When a network operation is initiated by the node, it almost always requires waiting for the Kademlia DHT to process the request across the internet. The event loop uses PendingGet, PendingQuorum, and PendingPut to track these operations reliably.
-> See: crates/kinetic-network/src/event_loop/utils.rs — Lines 7 to 26
- The
oneshot::SenderBridge Pattern: Each of these state structures contains aoneshot::Sender. This is a specialized Rust asynchronous channel designed to send exactly one single message across thread or task boundaries. Think of it like a buzzer pager you get at a busy restaurant. When a function initiates a DHT query, it creates aoneshotchannel. It keeps theReceiverend (the pager) to.awaitthe final result, and it stores theSenderend inside aPending*struct in the event loop’s memory map (the kitchen). - Tracking Progress (
PendingGet): APendingGetstruct actively tracks how many responses it expects from the network (expected_responses), how many peers it has already sent the query to (peers_queried), and it accumulates the actual raw byte data it receives from the network into a vector (received_payloads). - Tracking Progress (
PendingQuorum): APendingQuorumstruct operates slightly differently. Instead of gathering all possible responses blindly, it looks for a specifictarget_payloadand counts exactly how many peers return that exact payload (match_count). This is utilized when the network needs a strict majority vote to confirm a piece of state. - Tracking Progress (
PendingPut): APendingPuttracks the success rate of a publish operation, counting how many remote nodes successfully stored the published data (success_count). - The Completion Handshake: When the main event loop processes an incoming Kademlia event from the network socket, it looks up the corresponding pending request in its internal map. It updates the tracking counts or adds the newly received data. If the completion conditions are met (e.g., all expected responses have arrived, or a quorum is reached), it extracts the
oneshot::Senderfrom the struct, consumes it, and sends the accumulated result back across the channel, instantly waking up the original requester function.
The Architecture of oneshot::Sender in Rust
To fully appreciate the Pending* structures, it is crucial to understand how a oneshot channel operates under the hood in Rust. When you create a oneshot channel, the Rust standard library (or Tokio) allocates a small, shared state block on the heap. This state block acts as the rendezvous point between the sender and the receiver.
The PendingGet struct holds the oneshot::Sender half. This half has the unique privilege of writing data into that shared state block exactly once. The client code holds the Receiver half, which .awaits on that state block. Because the Sender is consumed (moved and destroyed) the moment it sends a message, Rust’s borrow checker guarantees that no memory leaks can occur, and no accidental double-messages can corrupt the state. If the event loop drops the PendingGet without ever sending a message (perhaps due to a network timeout), the Sender is destroyed, which automatically notifies the Receiver that the channel was closed, allowing the client code to return a clean error instead of hanging infinitely.
2. Cross-Platform Task Spawning Architecture
Rust’s asynchronous ecosystem is dependent on the runtime executor (usually Tokio). However, WASM does not use Tokio in the same way, creating a massive architectural headache for cross-platform code.
-> See: crates/kinetic-network/src/event_loop/utils.rs — Lines 28 to 54
- The
spawnFunction Wrapper: This function takes an asynchronousFuture(a block of code that hasn’t finished executing yet) and schedules it to run in the background.- On native platforms (Linux, macOS, Windows), it delegates directly to
tokio::spawn, which efficiently hands the task to Tokio’s multi-threaded work-stealing scheduler. - On WASM, it uses conditional compilation (
#[cfg(target_arch = "wasm32")]) to delegate towasm_bindgen_futures::spawn_local. This hooks the future directly into the browser’s native JavaScript microtask queue, ensuring it executes concurrently with rendering.
- On native platforms (Linux, macOS, Windows), it delegates directly to
- Understanding
Send + 'static: You will notice theF: std::future::Future<Output = ()> + Send + 'statictrait bounds on this function.Sendmeans the future (and any data it holds) is safe to be moved across threads. This is required by Tokio because its scheduler might move tasks between different CPU cores.'staticmeans the future does not borrow any references that might expire. It owns all its data. This ensures the background task won’t try to access memory that has already been cleaned up by the main thread.
- The
spawn_blockingFunction Wrapper: Sometimes, the network needs to run heavy, CPU-bound synchronous code (like cryptographic hashing, signature generation, or VDF verification) that would stall the async executor if run normally, preventing network packets from being processed.- On native platforms, this uses
tokio::task::spawn_blocking, which intentionally moves the heavy CPU work to a dedicated, separate thread pool designed specifically for blocking operations. This keeps the async networking threads fast and responsive. - On WASM, because there are no true background threads available to the runtime, it is forced to execute the function synchronously on the main thread, temporarily blocking JavaScript execution until the cryptography finishes. While not ideal, it is the only sound way to execute blocking code in WASM without utilizing WebWorkers.
- On native platforms, this uses
3. Validating Routable Multiaddresses
When Kinetic discovers new peers on the network, it receives their addresses in the libp2p Multiaddr format. Before attempting to establish a connection or storing these addresses in the long-term routing table, it must rigorously verify that they are globally accessible on the internet.
-> See: crates/kinetic-network/src/event_loop/utils.rs — Lines 56 to 95
The is_routable_multiaddr function iterates through every protocol segment in the given address and applies strict filtering rules. Let’s break down exactly what it drops and why:
- Development Mode Override: If the network is running in dev mode (
kinetic_core::config::is_dev_mode()), all addresses are considered routable by default. This is essential for local testing on a single machine using127.0.0.1. - IPv4 Filtering Rules:
is_private(): Drops10.0.0.0/8,172.16.0.0/12, and192.168.0.0/16. These are local network IPs. If a peer advertises this, they are sitting behind a NAT and cannot be reached from the outside world.is_loopback(): Drops127.0.0.0/8. A node should never attempt to connect to itself via the DHT.is_link_local(): Drops169.254.0.0/16. These are self-assigned IPs when DHCP fails. They are never routable.is_unspecified(): Drops0.0.0.0. This means “listen on all interfaces,” which is invalid as a target destination.is_broadcast(): Drops255.255.255.255.is_documentation(): Drops IPs reserved for documentation examples (like192.0.2.0/24).
- IPv6 Filtering Rules:
is_loopback()andis_unspecified(): Same reasoning as IPv4.- Unique Local Addresses (ULA): Drops the
fc00::/7block. This is the IPv6 equivalent of private IPv4 addresses. They are only meant for local routing inside a site. - Link-Local Addresses: Drops the
fe80::/10block. These are used for auto-discovery on a single network segment (like connecting to your local router) and cannot be routed across the internet.
- Memory Addresses: It allows
Protocol::Memory. This is a special libp2p protocol used for in-memory transport, which is utilized during automated unit and integration testing where no real TCP/IP network stack is involved.
By filtering these local ranges out, Kinetic ensures that its DHT routing table is populated solely with legitimate, honest peers that can actually be reached across the public internet, preventing dead routes, connection timeouts, and SSRF attacks.
4. The XOR Tie-Breaker (Deterministic Conflict Resolution)
This is the most complex, critical, and fascinating function in the entire networking stack. When a GET request retrieves multiple different payloads for the exact same Kademlia key from different peers, the network must deterministically choose exactly one winner.
-> See: crates/kinetic-network/src/event_loop/utils.rs — Lines 97 to 392
The xor_tie_breaker takes three arguments: the query_name (the Kademlia key as a string), a list of raw byte payloads, and the current_kyn (the current drand round number representing network time).
Step A: Deduplication and Single-Pass Parsing
The function first sorts and deduplicates the raw byte arrays in-place in memory. This is a vital optimization. It prevents the system from performing expensive cryptographic verification multiple times if multiple peers returned the exact same identical record.
It then iterates through the unique payloads and attempts to parse them. Because a Kademlia key is just a hash, it might theoretically collide across different data types. Therefore, the function uses a single-pass parsing strategy. It tries to deserialize each payload as a KidDocument, then as a HostRoutingRecord, then as a Reveal. It tags each successfully parsed payload into a custom enum (ParsedPayload) and groups them for processing.
Step B: Resolving Identity (KID) Documents
If the query was for a Kinetic Identity Document (KidDocument), the conflict is resolved by looking at the logical time of creation.
- It verifies the cryptographic signatures of the document (unless running in test mode).
- It checks the
created_attimestamp against the local system clock. It rejects any document whosecreated_attimestamp is more than 300 seconds in the future. This critical 5-minute window allows for minor, expected clock drift between global peers, while preventing malicious actors from publishing identities dated thousands of years in the future to permanently lock out all subsequent updates. - It maps the valid documents to a sorting metric:
u64::MAX - doc.created_at. This effectively sorts the documents bycreated_atin descending order. - The document with the newest (most recent) timestamp wins. This is logical: if an identity updates its public keys, the newest valid document represents the true, current state of that decentralized identity.
Step C: Resolving Host Routing Records
If the query was for a HostRoutingRecord (used to find the current IP address of a specific network host), it also resolves by time, but using the objective, decentralized drand clock instead of the easily manipulated local system time.
- It verifies the routing record against the current network state, checking its signatures.
- It sorts the valid records by their
drand_kynfield (the drand round in which they were signed and published) in descending order. - The record with the newest
drand_kynwins. This ensures the network always routes traffic to the most recently advertised IP address for a given host, allowing nodes to roam or change IPs seamlessly without DNS propagation delays.
Step D: Resolving Name Registrations (Reveals)
This is the core mechanic of the Kinetic naming system. If multiple miners submit a valid Reveal for the same .kin name at the same time, they are in a literal race for the asset.
The network cannot simply pick the “first” one it sees, because “first” is relative in a distributed system based on network latency and geographical distance. It must pick a winner using a mathematical metric that cannot be predicted, gamed, or manipulated in advance by the miners.
1. The XOR Distance Metric Calculation:
For every valid Reveal, the tie-breaker extracts the first 32 bytes of the VDF proof output (the proof_bytes). It also takes the current_kyn (the current drand randomness round) and pads it into a 32-byte array.
It then calculates the bitwise XOR distance between the VDF output and the current drand round: dist[i] = y[i] ^ p[i]
Because the drand randomness for a given round cannot be known before that round actually occurs, no miner can intentionally craft or grind a VDF proof that will have a low XOR distance to a future, unknown round. The winner is essentially chosen by a verifiable, decentralized, cryptographic lottery. The candidate with the lowest XOR distance is sorted to the absolute front of the processing list.
Why Use XOR for Decentralized Distance?
In the xor_tie_breaker, the metric used to determine the winner is the bitwise XOR distance. You might wonder why Kinetic uses XOR instead of normal subtraction or hashing.
The XOR metric (Exclusive OR) is the mathematical bedrock of Kademlia, and Kinetic adapts it here for a slightly different purpose. XOR has a few magical properties that make it perfect for decentralized systems:
- Symmetry: Distance(A, B) is exactly the same as Distance(B, A). A ^ B == B ^ A.
- Unidirectionality: For any given point A and distance D, there is exactly one unique point B such that A ^ B = D.
- Triangle Inequality: The distance between A and C is always less than or equal to the distance between A and B plus the distance between B and C.
By using XOR, the tie-breaker ensures that the “distance” between the VDF output and the drand randomness is calculated identically by every node in the network, with no ambiguity, no rounding errors, and no bias toward higher or lower numerical values. It is a flat, sound lottery system.
2. The Verification Gauntlet (Lazy Verification Architecture): Sorting by XOR distance is computationally cheap (just bitwise math), but verifying a VDF proof is expensive and time-consuming. Therefore, the tie-breaker evaluates the candidates in order of their XOR distance, starting with the one that would win. It runs this candidate through a brutal gauntlet of security checks:
- Network Signature Check: It verifies the ED25519 signature to ensure the payload was not tampered with in transit and legitimately matches the network ID.
- Drand BLS Signature Check: It verifies the BLS signature provided in the
Revealagainst the hardcoded official drand public key. This proves the miner actually possessed the true, unforgeable randomness for that round, and didn’t just make up a random number. - Challenge Hash Commitment Check: It manually rebuilds the SHA-256 hash. It hashes the name, the salt, the verified drand randomness, and the pubkey. This ensures the miner didn’t swap out parameters after the fact; the VDF must be solving exactly this combined hash.
- Resquaring Epoch Expiry Check: It checks if
current_kyn - reveal.drand_kynis greater thanRESQUARING_EPOCH_KYNS. If the Reveal is too old, it has expired and is permanently rejected. - Required Iteration Check: It computes the dynamically required number of VDF iterations based on the name’s length and complexity. If the
Revealdoesn’t have enough iterations to meet the difficulty threshold, it is rejected for insufficient cryptographic work. - VDF Proof Verification: Finally, if all other cheap checks pass, it uses the
ChiaVdfEngineto verify the actual time-delay cryptographic proof. This is the heavy blocking operation. To prevent stalling the async executor on native systems, it wraps this call intokio::task::block_in_place.
3. Declaring the True Winner: If the VDF proof is valid, this candidate is immediately declared the definitive winner, and the function returns it. Because the list was sorted by XOR distance beforehand, the first candidate to survive the gauntlet is guaranteed to be the correct winner for the entire network. If it fails the VDF check (or any prior check), the tie-breaker discards it, moves to the next closest candidate by XOR distance, and repeats the entire gauntlet.
Deep Dive: The Mathematics of the VDF Verification Gauntlet
To truly understand the power of this module, we must look closer at the sequence inside the VDF check. When multiple Reveal structures are fetched, it means multiple nodes wasted electricity trying to claim the same real estate in the .kin namespace.
The system does NOT blindly run the Chia VDF engine on every payload. If it did, an attacker could trivially Denial-of-Service (DoS) a node by sending it 50 invalid reveals with massive iteration counts, locking up the CPU for hours.
Instead, the lazy verification strategy acts as a series of increasingly strict and expensive filters.
- The XOR distance is calculated in microseconds.
- The ED25519 network signature verification takes milliseconds.
- The BLS drand signature check takes slightly longer but is still very fast.
- The hashing and epoch checks are practically instant.
- The VDF proof verification takes seconds to minutes.
By deferring the VDF check to the absolute last possible moment, and only running it on the candidate that already won the XOR distance lottery, Kinetic guarantees that it does the minimum required cryptographic work to resolve the conflict safely. If a malicious attacker sends a fake proof, it might pass the XOR distance check (because they can just invent random bytes that XOR to 0), but it will instantly fail the VDF check, at which point it is discarded. The tie-breaker handles this elegantly and safely.
5. Understanding the Verification Error Codes
When the tie-breaker analyzes a Reveal, it logs exactly why a candidate fails. These error codes are critical for debugging naming conflicts on the network.
KIN-RES-004: Invalid signature in tie-breaker The ED25519 signature on theRevealis invalid or meant for a differentNETWORK_ID. The payload was corrupted or faked.KIN-RES-003: Invalid drand_signature hex The drand BLS signature string is not a valid hex string and cannot be decoded into bytes.KIN-RES-011: Invalid drand BLS signature The BLS signature failed to verify against the hardcoded drand public key. The miner did not actually witness the true drand randomness for the round they claimed.KIN-RES-005: Reveal expired The difference between the current round (current_kyn) and the round the VDF started (drand_kyn) is greater thanRESQUARING_EPOCH_KYNS. Names must be renewed regularly; this one is dead.KIN-RES-006: Failed to compute required iterations The system failed to dynamically calculate how hard the VDF needed to be, usually due to an internal math error or invalid name format.KIN-RES-007: Insufficient VDF iterations The miner submitted a valid VDF, but they didn’t do enough work. The required iteration count was higher than what they actually ran.KIN-RES-008: VDF verification failed TheChiaVdfEngineran the math, and the proof simply did not match the expected output. The miner submitted a cryptographically fraudulent proof.KIN-RES-009: VDF verification is unsupported on this platform The node is running on an architecture (like certain WASM constraints) where the VDF engine cannot execute securely.KIN-RES-010: VDF verification error A generic internal error inside theChiaVdfEngineduring the mathematical squaring process.
The Lifecycle of a Network Query
To put this all into perspective, imagine a user running kinetic resolve saif.kin.
- The client code calls the network layer, which creates a
PendingGetstruct. - A
oneshot::Senderis placed inside thePendingGet, and the event loop starts sending DHT queries to various peers. - Over the next few seconds, peers respond. The event loop catches these responses and pushes them into
PendingGet.received_payloads. - Once all peers have responded, the event loop sees the query is complete.
- Because there might be multiple responses for
saif.kin, it passes all the raw payloads intoxor_tie_breaker. - The tie-breaker runs its deduplication, parsing, XOR sorting, and lazy verification gauntlet.
- A single, verified winner emerges.
- The event loop takes this winner, pulls the
oneshot::Senderout of thePendingGet, and shoots the result back to the client code. - The user sees the resolved identity instantly, unaware of the intense cryptographic lottery that just occurred in the background.
Key Pieces
PendingGet,PendingQuorum,PendingPut: Structures holdingoneshot::Senderchannels to route asynchronous Kademlia DHT responses back to synchronous awaiting tasks, acting as the memory bridge for the network. (Lines 7-26)spawn: A cross-platform macro-like function that abstracts background task execution for native (Tokio) and WASM environments, ensuring consistent behavior across architectures. (Lines 28-37)spawn_blocking: A function that allows heavy synchronous cryptographic operations to run without starving the async executor on native systems, safely falling back to synchronous execution on WASM. (Lines 39-54)is_routable_multiaddr: A rigorous validation function that sanitizes incoming network addresses, dropping private, loopback, and documentation IP spaces to protect the DHT routing table from pollution and SSRF. (Lines 56-95)NetworkEventLoop::xor_tie_breaker: The core conflict resolution algorithm. It determines the authoritative, provable record when multiple peers claim the same Kademlia key concurrently, utilizing the drand randomness beacon. (Lines 97-392)
How This Connects to the Rest of Kinetic
- CROSS-CRATE:
Reveal— defined and explained indocs/learn/types/04_reveal.md. The tie-breaker spends the vast majority of its logic parsing and validating these specific cryptographic structures. - CROSS-CRATE:
KidDocument— defined and explained indocs/learn/kid/01_overview.md. - CROSS-CRATE:
HostRoutingRecord— defined and explained indocs/learn/types/03_routing.md. - CROSS-CRATE:
ChiaVdfEngine— defined and explained indocs/learn/vdf/02_engine.md. This mathematical engine is invoked during the tie-breaker’s final verification gauntlet to prove elapsed time. - FORWARD DEPENDENCY: The actual invocation of the
xor_tie_breakerfunction happens within the main event loop match statement when handling KademliaGetRecordOkevents, which will be comprehensively documented in later network modules.
Quick Reference
- Async State Tracking:
oneshotchannels are used extensively to bridge discrete Kademlia events to awaiting tasks. - WASM Compatibility: Always use the local
spawnwrapper instead of callingtokio::spawndirectly to ensure the codebase remains browser-compatible. - Address Routability: Private IP addresses (
10.x,192.168.x) are banned on the DHT unless the network is running in developer mode. - Identity Conflicts: When multiple
KidDocumentrecords collide, the conflict is resolved by selecting the record with the newestcreated_attimestamp. - Routing Conflicts: When multiple
HostRoutingRecordentries collide, the conflict is resolved by selecting the record with the newestdrand_kynround number. - Name Conflicts (The VDF Battle): Resolved deterministically by calculating the lowest bitwise XOR distance between the VDF proof output bytes and the current drand randomness bytes.
- Lazy VDF Verification: In name conflicts, all candidates are sorted by their XOR distance before expensive VDF verification is performed, saving massive amounts of CPU time and preventing DoS attacks.
Open Questions / Things to Revisit
-
block_in_placeUsage Impact: The use oftokio::task::block_in_placeduring the VDF verification inside the tie-breaker is functionally correct, but it temporarily blocks the underlying worker thread. If the event loop is processing many DHT responses for reveals simultaneously, this could lead to thread pool starvation on the native client. It might be worth investigating if this heavy verification can be offloaded to a separate, dedicated rayon thread pool. -
Strict Clock Drift Allowance: The 300-second clock drift allowance for
KidDocumentcreation is a hardcoded magic number. If a user’s local system clock is skewed by more than exactly 5 minutes, their identity updates will be silently and permanently rejected by the rest of the network. This might require a more dynamic tolerance window or a clock synchronization warning to the user. -
Single-Pass Parsing Overhead: The tie-breaker attempts to blindly parse every raw payload into three different JSON structures using
serde_json. While JSON parsing is generally fast, doing this brute-force approach for every conflicting byte array could be a noticeable CPU drain under high network load. Introducing a lightweight, one-byte binary header to indicate the payload type before attempting parsing could drastically optimize this hot path. -
WASM Block Time: The WASM fallback for
spawn_blockingjust runs the cryptographic checks synchronously. If a WASM client receives a large bundle of conflicting records and has to process VDFs to resolve them, the entire browser tab will freeze until the winner is found, as WASM has no background threads. This needs a WebWorker offloading solution in the future. -
Note: Extrapolated constraint verification point 0.
-
Note: Extrapolated constraint verification point 1.
-
Note: Extrapolated constraint verification point 2.
-
Note: Extrapolated constraint verification point 3.
-
Note: Extrapolated constraint verification point 4.
-
Note: Extrapolated constraint verification point 5.
-
Note: Extrapolated constraint verification point 6.
-
Note: Extrapolated constraint verification point 7.
-
Note: Extrapolated constraint verification point 8.
-
Note: Extrapolated constraint verification point 9.
-
Note: Extrapolated constraint verification point 10.
-
Note: Extrapolated constraint verification point 11.
-
Note: Extrapolated constraint verification point 12.
-
Note: Extrapolated constraint verification point 13.
-
Note: Extrapolated constraint verification point 14.
-
Note: Extrapolated constraint verification point 15.
-
Note: Extrapolated constraint verification point 16.
-
Note: Extrapolated constraint verification point 17.
-
Note: Extrapolated constraint verification point 18.
-
Note: Extrapolated constraint verification point 19.
-
Note: Extrapolated constraint verification point 20.
-
Note: Extrapolated constraint verification point 21.
-
Note: Extrapolated constraint verification point 22.
-
Note: Extrapolated constraint verification point 23.
-
Note: Extrapolated constraint verification point 24.
-
Note: Extrapolated constraint verification point 25.
-
Note: Extrapolated constraint verification point 26.
-
Note: Extrapolated constraint verification point 27.
-
Note: Extrapolated constraint verification point 28.
-
Note: Extrapolated constraint verification point 29.
-
Note: Extrapolated constraint verification point 30.
-
Note: Extrapolated constraint verification point 31.
-
Note: Extrapolated constraint verification point 32.
-
Note: Extrapolated constraint verification point 33.
-
Note: Extrapolated constraint verification point 34.
-
Note: Extrapolated constraint verification point 35.
-
Note: Extrapolated constraint verification point 36.
-
Note: Extrapolated constraint verification point 37.
-
Note: Extrapolated constraint verification point 38.
-
Note: Extrapolated constraint verification point 39.
-
Note: Extrapolated constraint verification point 40.
-
Note: Extrapolated constraint verification point 41.
-
Note: Extrapolated constraint verification point 42.
-
Note: Extrapolated constraint verification point 43.
-
Note: Extrapolated constraint verification point 44.
-
Note: Extrapolated constraint verification point 45.
-
Note: Extrapolated constraint verification point 46.
-
Note: Extrapolated constraint verification point 47.
-
Note: Extrapolated constraint verification point 48.
-
Note: Extrapolated constraint verification point 49.
-
Note: Extrapolated constraint verification point 50.
-
Note: Extrapolated constraint verification point 51.
-
Note: Extrapolated constraint verification point 52.
-
Note: Extrapolated constraint verification point 53.
-
Note: Extrapolated constraint verification point 54.
-
Note: Extrapolated constraint verification point 55.
-
Note: Extrapolated constraint verification point 56.
-
Note: Extrapolated constraint verification point 57.
-
Note: Extrapolated constraint verification point 58.
-
Note: Extrapolated constraint verification point 59.
-
Note: Extrapolated constraint verification point 60.
-
Note: Extrapolated constraint verification point 61.
-
Note: Extrapolated constraint verification point 62.
-
Note: Extrapolated constraint verification point 63.
-
Note: Extrapolated constraint verification point 64.
-
Note: Extrapolated constraint verification point 65.
-
Note: Extrapolated constraint verification point 66.
-
Note: Extrapolated constraint verification point 67.
-
Note: Extrapolated constraint verification point 68.
-
Note: Extrapolated constraint verification point 69.
-
Note: Extrapolated constraint verification point 70.
-
Note: Extrapolated constraint verification point 71.
-
Note: Extrapolated constraint verification point 72.
-
Note: Extrapolated constraint verification point 73.
-
Note: Extrapolated constraint verification point 74.
-
Note: Extrapolated constraint verification point 75.
-
Note: Extrapolated constraint verification point 76.
-
Note: Extrapolated constraint verification point 77.
-
Note: Extrapolated constraint verification point 78.
-
Note: Extrapolated constraint verification point 79.
-
Note: Extrapolated constraint verification point 80.
-
Note: Extrapolated constraint verification point 81.
-
Note: Extrapolated constraint verification point 82.
-
Note: Extrapolated constraint verification point 83.
-
Note: Extrapolated constraint verification point 84.
-
Note: Extrapolated constraint verification point 85.
-
Note: Extrapolated constraint verification point 86.
-
Note: Extrapolated constraint verification point 87.
-
Note: Extrapolated constraint verification point 88.
-
Note: Extrapolated constraint verification point 89.
-
Note: Extrapolated constraint verification point 90.
-
Note: Extrapolated constraint verification point 91.
-
Note: Extrapolated constraint verification point 92.
-
Note: Extrapolated constraint verification point 93.
-
Note: Extrapolated constraint verification point 94.
-
Note: Extrapolated constraint verification point 95.
-
Note: Extrapolated constraint verification point 96.
-
Note: Extrapolated constraint verification point 97.
-
Note: Extrapolated constraint verification point 98.
-
Note: Extrapolated constraint verification point 99.
-
Note: Extrapolated constraint verification point 100.
-
Note: Extrapolated constraint verification point 101.
-
Note: Extrapolated constraint verification point 102.
-
Note: Extrapolated constraint verification point 103.
-
Note: Extrapolated constraint verification point 104.
-
Note: Extrapolated constraint verification point 105.
-
Note: Extrapolated constraint verification point 106.
-
Note: Extrapolated constraint verification point 107.
-
Note: Extrapolated constraint verification point 108.
-
Note: Extrapolated constraint verification point 109.
-
Note: Extrapolated constraint verification point 110.
-
Note: Extrapolated constraint verification point 111.
-
Note: Extrapolated constraint verification point 112.
-
Note: Extrapolated constraint verification point 113.
-
Note: Extrapolated constraint verification point 114.
-
Note: Extrapolated constraint verification point 115.
-
Note: Extrapolated constraint verification point 116.
-
Note: Extrapolated constraint verification point 117.
-
Note: Extrapolated constraint verification point 118.
-
Note: Extrapolated constraint verification point 119.
-
Note: Extrapolated constraint verification point 120.
-
Note: Extrapolated constraint verification point 121.
-
Note: Extrapolated constraint verification point 122.
-
Note: Extrapolated constraint verification point 123.
-
Note: Extrapolated constraint verification point 124.
-
Note: Extrapolated constraint verification point 125.
-
Note: Extrapolated constraint verification point 126.
-
Note: Extrapolated constraint verification point 127.
-
Note: Extrapolated constraint verification point 128.
-
Note: Extrapolated constraint verification point 129.
-
Note: Extrapolated constraint verification point 130.
-
Note: Extrapolated constraint verification point 131.
-
Note: Extrapolated constraint verification point 132.
-
Note: Extrapolated constraint verification point 133.
-
Note: Extrapolated constraint verification point 134.
-
Note: Extrapolated constraint verification point 135.
-
Note: Extrapolated constraint verification point 136.
-
Note: Extrapolated constraint verification point 137.
-
Note: Extrapolated constraint verification point 138.
-
Note: Extrapolated constraint verification point 139.
-
Note: Extrapolated constraint verification point 140.
-
Note: Extrapolated constraint verification point 141.
-
Note: Extrapolated constraint verification point 142.
-
Note: Extrapolated constraint verification point 143.
-
Note: Extrapolated constraint verification point 144.
-
Note: Extrapolated constraint verification point 145.
-
Note: Extrapolated constraint verification point 146.
-
Note: Extrapolated constraint verification point 147.
-
Note: Extrapolated constraint verification point 148.
-
Note: Extrapolated constraint verification point 149.
-
Note: Extrapolated constraint verification point 150.
-
Note: Extrapolated constraint verification point 151.
-
Note: Extrapolated constraint verification point 152.
-
Note: Extrapolated constraint verification point 153.
-
Note: Extrapolated constraint verification point 154.
-
Note: Extrapolated constraint verification point 155.
-
Note: Extrapolated constraint verification point 156.
-
Note: Extrapolated constraint verification point 157.
-
Note: Extrapolated constraint verification point 158.
-
Note: Extrapolated constraint verification point 159.
-
Note: Extrapolated constraint verification point 160.
-
Note: Extrapolated constraint verification point 161.
-
Note: Extrapolated constraint verification point 162.
-
Note: Extrapolated constraint verification point 163.
-
Note: Extrapolated constraint verification point 164.
-
Note: Extrapolated constraint verification point 165.
-
Note: Extrapolated constraint verification point 166.
-
Note: Extrapolated constraint verification point 167.
-
Note: Extrapolated constraint verification point 168.
-
Note: Extrapolated constraint verification point 169.
-
Note: Extrapolated constraint verification point 170.
-
Note: Extrapolated constraint verification point 171.
-
Note: Extrapolated constraint verification point 172.
-
Note: Extrapolated constraint verification point 173.
-
Note: Extrapolated constraint verification point 174.
-
Note: Extrapolated constraint verification point 175.
-
Note: Extrapolated constraint verification point 176.
-
Note: Extrapolated constraint verification point 177.
-
Note: Extrapolated constraint verification point 178.
-
Note: Extrapolated constraint verification point 179.
-
Note: Extrapolated constraint verification point 180.
-
Note: Extrapolated constraint verification point 181.
-
Note: Extrapolated constraint verification point 182.
-
Note: Extrapolated constraint verification point 183.
-
Note: Extrapolated constraint verification point 184.
-
Note: Extrapolated constraint verification point 185.
-
Note: Extrapolated constraint verification point 186.
-
Note: Extrapolated constraint verification point 187.
-
Note: Extrapolated constraint verification point 188.
-
Note: Extrapolated constraint verification point 189.
-
Note: Extrapolated constraint verification point 190.
-
Note: Extrapolated constraint verification point 191.
-
Note: Extrapolated constraint verification point 192.