Complete API documentation for the VTP Node project
Overview • Rust Core API • Consensus API • Network API • Web Worker API • Svelte Stores • Utility Functions
- Overview
- Rust Core API
- Consensus API
- Network API
- Web Worker API
- Svelte Stores
- Utility Functions
- TypeScript Interfaces
- Error Codes
- Examples
The VTP Node project exposes APIs at multiple levels:
- Rust Core API (
vtp-core): Low-level cryptographic functions compiled to WebAssembly - Web Worker API: Message-based interface for background computation
- Svelte Stores: Reactive state management for the UI
- Utility Functions: Helper functions for common operations
- Consensus API: VRF-driven leader election + BFT validation
- Network API: WebRTC P2P networking with signaling
- Type Safety: All APIs use TypeScript/Rust type system for compile-time checks
- Immutability: State updates are immutable where possible
- Error Handling: All fallible operations return Result types
- Performance: APIs are optimized for browser environments
The vtp-core crate provides the core cryptographic functionality. It is compiled to WebAssembly and can be called from JavaScript.
The VDF (Verifiable Delay Function) module implements Wesolowski's construction over imaginary quadratic class groups.
Execute a single VDF step (class group squaring).
pub fn vdf_step(state: &[u8; 32]) -> [u8; 32]Parameters:
| Parameter | Type | Description |
|---|---|---|
state |
[u8; 32] |
Current VDF state seed (32 bytes) |
Returns:
[u8; 32]: Hash of the squared class group element
Example:
let state = [0u8; 32];
let next_state = vdf_step(&state);
assert_eq!(next_state.len(), 32);Iterator for batch VDF processing.
pub struct VdfIterator {
state: VdfState,
step: u64,
total: u64,
discriminant: BigInt,
generator: ClassGroupElement,
}Create a new VDF iterator.
pub fn new(seed: &[u8], total: u64) -> SelfParameters:
| Parameter | Type | Description |
|---|---|---|
seed |
&[u8] |
Initial seed (at least 32 bytes) |
total |
u64 |
Total steps target |
Returns: VdfIterator instance
Panics: If seed is less than 32 bytes
Get current step count.
pub fn step(&self) -> u64Returns: Current step count
Get total steps target.
pub fn total(&self) -> u64Returns: Total steps target
Check if computation is finished.
pub fn is_finished(&self) -> boolReturns:
true: All steps completedfalse: Steps remaining
Get current VDF state.
pub fn get_state(&self) -> Vec<u8>Returns: Variable-length state vector (serialised class group element)
Execute single step.
pub fn next(&mut self) -> boolReturns:
true: Step executed successfullyfalse: Already finished
Execute batch of steps.
pub fn run_batch(&mut self, max_steps: u64) -> u64Parameters:
| Parameter | Type | Description |
|---|---|---|
max_steps |
u64 |
Maximum steps to execute |
Returns: Number of steps actually executed
Example:
let seed = [0u8; 32];
let mut iter = VdfIterator::new(&seed, 1000);
let steps = iter.run_batch(100);
assert_eq!(steps, 100);Generate a Wesolowski proof for a completed VDF computation.
pub fn generate_proof(seed: &[u8], state_bytes: &[u8], total: u64) -> Vec<u8>Parameters:
| Parameter | Type | Description |
|---|---|---|
seed |
&[u8] |
Original VDF seed (at least 32 bytes) |
state_bytes |
&[u8] |
Serialised final state (output y) |
total |
u64 |
Time parameter T |
Returns: The Wesolowski proof as bytes (serialised class group element)
Verify a Wesolowski proof. Checks that pi^l * g^q == y where l = Hash(g, y, T).
pub fn verify_proof(seed: &[u8], state_bytes: &[u8], total: u64, proof_bytes: &[u8]) -> boolParameters:
| Parameter | Type | Description |
|---|---|---|
seed |
&[u8] |
Original VDF seed |
state_bytes |
&[u8] |
Claimed output y |
total |
u64 |
Time parameter T |
proof_bytes |
&[u8] |
The proof pi |
Returns:
true: The proof is validfalse: The proof is invalid
The VRF (Verifiable Random Function) module implements ECVRF-ED25519.
Generate a new VRF keypair.
pub fn generate_keypair() -> VrfKeypairReturns: VrfKeypair containing public and secret keys
Example:
let keypair = generate_keypair();
println!("Public key: {:?}", keypair.public_key());VRF keypair structure.
pub struct VrfKeypair {
public_key: Vec<u8>,
secret_key: Vec<u8>,
}Get public key.
#[wasm_bindgen(getter)]
pub fn public_key(&self) -> Vec<u8>Returns: 32-byte public key vector
Get secret key.
#[wasm_bindgen(getter)]
pub fn secret_key(&self) -> Vec<u8>Returns: 32-byte secret key vector
Security: Keep secret key secure, never share
Generate VRF proof.
pub fn prove(secret_key: &[u8], message: &[u8]) -> Vec<u8>Parameters:
| Parameter | Type | Description |
|---|---|---|
secret_key |
&[u8] |
32-byte secret key |
message |
&[u8] |
Message to sign |
Returns: 64-byte signature vector
Panics: If secret_key is not 32 bytes
Example:
let keypair = generate_keypair();
let message = b"challenge data";
let proof = prove(&keypair.secret_key(), message);Verify VRF proof.
pub fn verify(public_key: &[u8], message: &[u8], proof: &[u8]) -> boolParameters:
| Parameter | Type | Description |
|---|---|---|
public_key |
&[u8] |
32-byte public key |
message |
&[u8] |
Original message |
proof |
&[u8] |
64-byte signature |
Returns:
true: Proof is validfalse: Proof is invalid
Generate a Wesolowski proof for the completed VDF computation.
pub fn generate_vdf_proof(&self) -> Vec<u8>Returns: The Wesolowski proof as bytes (serialised class group element)
Panics: If the VDF computation has not finished yet
Verify a Wesolowski proof against the current session state.
pub fn verify_vdf_proof(&self, proof_bytes: &[u8]) -> boolParameters:
| Parameter | Type | Description |
|---|---|---|
proof_bytes |
&[u8] |
The Wesolowski proof bytes |
Returns:
true: The proof is validfalse: The proof is invalid or verification failed
Example:
let keypair = generate_keypair();
let message = b"challenge data";
let proof = prove(&keypair.secret_key(), message);
assert!(verify(&keypair.public_key(), message, &proof));The Session module manages complete VDF challenge lifecycle.
Batch computation result enum.
#[wasm_bindgen]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum BatchResult {
Progress(u64),
Winner(u64, Vec<u8>),
Finished,
Error(VtpError),
}Variants:
| Variant | Description |
|---|---|
Progress(u64) |
Computation in progress, returns current step |
Winner(u64, Vec<u8>) |
Winner found, returns step and VRF proof |
Finished |
VDF computation completed |
Error(VtpError) |
Error occurred |
Session state structure.
#[wasm_bindgen]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionState {
pub step: u64,
pub total: u64,
pub is_active: bool,
pub is_paused: bool,
pub error_count: u32,
}Fields:
| Field | Type | Description |
|---|---|---|
step |
u64 |
Current completed steps |
total |
u64 |
Total steps target |
is_active |
bool |
Session is active (not finished) |
is_paused |
bool |
Session is paused |
error_count |
u32 |
Number of errors occurred |
VDF challenge session manager.
pub struct Session {
vdf: VdfIterator,
seed: Vec<u8>,
keypair: VrfKeypair,
k: u64,
tau: Vec<u8>,
checkpoint_interval: u64,
error_handler: ErrorHandler,
is_paused: bool,
}Create new session.
#[wasm_bindgen(constructor)]
pub fn new(
seed: &[u8],
total: u64,
k: u64,
tau: &[u8],
checkpoint_interval: u64,
) -> SelfParameters:
| Parameter | Type | Description |
|---|---|---|
seed |
&[u8] |
VDF seed (at least 32 bytes) |
total |
u64 |
Total VDF steps |
k |
u64 |
VRF sampling interval |
tau |
&[u8] |
Threshold (32 bytes) |
checkpoint_interval |
u64 |
Checkpoint interval |
Returns: New Session instance
Example:
let seed = [0u8; 32];
let tau = [0u8; 32];
let session = Session::new(&seed, 1000000, 1000, &tau, 100000);Get current session state.
#[wasm_bindgen(getter)]
pub fn state(&self) -> SessionStateReturns: SessionState structure
Get VRF public key.
#[wasm_bindgen(getter)]
pub fn public_key(&self) -> Vec<u8>Returns: 32-byte public key vector
Pause session.
pub fn pause(&mut self)Resume session.
pub fn resume(&mut self)Check if session is paused.
pub fn is_paused(&self) -> boolReturns:
true: Session is pausedfalse: Session is running
Execute batch VDF computation.
pub fn run_batch(&mut self, max_steps: u64) -> BatchResultParameters:
| Parameter | Type | Description |
|---|---|---|
max_steps |
u64 |
Maximum steps to execute |
Returns: BatchResult enum
Example:
let mut session = Session::new(&seed, 1000000, 1000, &tau, 100000);
loop {
match session.run_batch(1000) {
BatchResult::Progress(step) => println!("Progress: {}", step),
BatchResult::Winner(step, proof) => println!("Winner at step {}", step),
BatchResult::Finished => break,
BatchResult::Error(err) => eprintln!("Error: {}", err),
}
}Get checkpoint data for persistence.
pub fn get_checkpoint_data(&self) -> Vec<u8>Returns: Serialized checkpoint data
Format: [8 bytes step (big-endian)] [variable-length VDF state (class group element)]
Verify winner proof.
pub fn verify_winner(&self, step: u64, proof: &[u8]) -> boolParameters:
| Parameter | Type | Description |
|---|---|---|
step |
u64 |
Winner step |
proof |
&[u8] |
VRF proof |
Returns:
true: Proof is validfalse: Proof is invalid
Error types and error handler.
VTP error enum.
#[wasm_bindgen]
#[derive(Debug, Clone, PartialEq)]
pub enum VtpError {
InvalidInput,
InvalidState,
ComputationFailed,
CheckpointFailed,
SessionFinished,
SessionNotStarted,
}Variants:
| Variant | Description |
|---|---|
InvalidInput |
Invalid input parameters |
InvalidState |
Invalid internal state |
ComputationFailed |
Computation failed |
CheckpointFailed |
Checkpoint save/load failed |
SessionFinished |
Session already finished |
SessionNotStarted |
Session not started |
Error handler with retry logic.
#[derive(Debug, Clone)]
pub struct ErrorHandler {
pub last_error: Option<VtpError>,
pub error_count: u32,
pub max_retries: u32,
}Create new error handler.
pub fn new(max_retries: u32) -> SelfParameters:
| Parameter | Type | Description |
|---|---|---|
max_retries |
u32 |
Maximum retry attempts |
Handle error and check if can retry.
pub fn handle_error(&mut self, error: VtpError) -> boolParameters:
| Parameter | Type | Description |
|---|---|---|
error |
VtpError |
Error to handle |
Returns:
true: Can continue (not exceeded max retries)false: Should stop (exceeded max retries)
Reset error state.
pub fn reset(&mut self)Check if can retry.
pub fn can_retry(&self) -> boolReturns:
true: Can retryfalse: Max retries reached
Utility functions.
Calculate SHA256 hash.
#[wasm_bindgen]
pub fn hash_bytes(data: &[u8]) -> Vec<u8>Parameters:
| Parameter | Type | Description |
|---|---|---|
data |
&[u8] |
Data to hash |
Returns: 32-byte hash vector
Convert bytes to hex string.
#[wasm_bindgen]
pub fn bytes_to_hex(bytes: &[u8]) -> StringParameters:
| Parameter | Type | Description |
|---|---|---|
bytes |
&[u8] |
Bytes to convert |
Returns: Hex string (lowercase)
Example:
let bytes = vec![0x00, 0x0f, 0xff];
let hex = bytes_to_hex(&bytes);
assert_eq!(hex, "000fff");Convert hex string to bytes.
#[wasm_bindgen]
pub fn hex_to_bytes(hex: &str) -> Result<Vec<u8>, JsValue>Parameters:
| Parameter | Type | Description |
|---|---|---|
hex |
&str |
Hex string |
Returns:
Ok(Vec<u8>): Converted bytesErr(JsValue): Conversion error
Errors:
- Odd length string
- Non-hex characters
Generate random bytes.
#[wasm_bindgen]
pub fn generate_random_bytes(length: u32) -> Vec<u8>Parameters:
| Parameter | Type | Description |
|---|---|---|
length |
u32 |
Number of bytes to generate |
Returns: Random bytes vector
Security: Uses OS random number generator
The Consensus API implements VRF-driven leader election with BFT-style voting (propose, prevote, precommit, commit). It is available as both a Rust/WASM module and a TypeScript wrapper.
The consensus module in vtp-core provides the low-level consensus primitives compiled to WebAssembly.
Consensus phase enum.
#[wasm_bindgen]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ConsensusPhase {
Propose,
Prevote,
Precommit,
Commit,
}Variants:
| Variant | Description |
|---|---|
Propose |
Leader proposes a block |
Prevote |
Validators prevote on proposal |
Precommit |
Validators precommit after prevote quorum |
Commit |
Block committed after precommit quorum |
Vote phase enum (subset of ConsensusPhase for vote messages).
#[wasm_bindgen]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum VotePhase {
Prevote,
Precommit,
}Block header structure.
#[wasm_bindgen]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BlockHeader {
pub round: u64,
pub prev_hash: Vec<u8>,
pub vdf_state: Vec<u8>,
pub vrf_proof: Vec<u8>,
pub proposer: Vec<u8>,
pub timestamp: u64,
}Fields:
| Field | Type | Description |
|---|---|---|
round |
u64 |
Consensus round number |
prev_hash |
Vec<u8> |
Hash of the previous block |
vdf_state |
Vec<u8> |
VDF state at time of proposal |
vrf_proof |
Vec<u8> |
VRF proof of leader election |
proposer |
Vec<u8> |
Proposer public key |
timestamp |
u64 |
Block timestamp (Unix ms) |
Create a new block header.
#[wasm_bindgen(constructor)]
pub fn new(
round: u64,
prev_hash: Vec<u8>,
vdf_state: Vec<u8>,
vrf_proof: Vec<u8>,
proposer: Vec<u8>,
timestamp: u64,
) -> SelfSerialize the header to bytes.
pub fn to_bytes(&self) -> Vec<u8>Deserialize a header from bytes.
pub fn from_bytes(bytes: &[u8]) -> Result<BlockHeader, JsValue>Compute the SHA-256 hash of this block header.
pub fn hash(&self) -> Vec<u8>Returns: 32-byte hash vector
pub fn round(&self) -> u64
pub fn prev_hash(&self) -> Vec<u8>
pub fn vdf_state(&self) -> Vec<u8>
pub fn vrf_proof(&self) -> Vec<u8>
pub fn proposer(&self) -> Vec<u8>
pub fn timestamp(&self) -> u64BFT consensus engine with VRF-driven leader election.
pub struct ConsensusEngine {
secret_key: Vec<u8>,
public_key: Vec<u8>,
validators: Vec<Vec<u8>>,
tau: Vec<u8>,
round: u64,
phase: ConsensusPhase,
vote_pool: VotePool,
chain: BlockChain,
}Create a new consensus engine (native Rust usage).
pub fn new_native(
secret_key: Vec<u8>,
public_key: Vec<u8>,
validators: Vec<Vec<u8>>,
tau: Vec<u8>,
) -> SelfParameters:
| Parameter | Type | Description |
|---|---|---|
secret_key |
Vec<u8> |
32-byte secret key |
public_key |
Vec<u8> |
32-byte public key |
validators |
Vec<Vec<u8>> |
List of validator public keys |
tau |
Vec<u8> |
32-byte VRF threshold |
Create a new consensus engine (WASM constructor).
#[wasm_bindgen(constructor)]
pub fn new(
secret_key: Vec<u8>,
public_key: Vec<u8>,
validator_keys: Vec<u8>,
tau: Vec<u8>,
) -> SelfParameters:
| Parameter | Type | Description |
|---|---|---|
secret_key |
Vec<u8> |
32-byte secret key |
public_key |
Vec<u8> |
32-byte public key |
validator_keys |
Vec<u8> |
Concatenated 32-byte validator public keys |
tau |
Vec<u8> |
32-byte VRF threshold |
Start a new consensus round and generate VRF proof.
pub fn start_round(&mut self, round: u64) -> Vec<u8>Parameters:
| Parameter | Type | Description |
|---|---|---|
round |
u64 |
Round number to start |
Returns: VRF proof bytes
Check if this node is the leader for the current round.
pub fn is_leader(&self) -> boolReturns: true if this node won VRF leader election
Create a block proposal (native Rust).
pub fn propose_native(
&mut self,
vdf_state: Vec<u8>,
timestamp: u64,
) -> Result<Vec<u8>, String>Parameters:
| Parameter | Type | Description |
|---|---|---|
vdf_state |
Vec<u8> |
Current VDF state |
timestamp |
u64 |
Block timestamp |
Returns: Serialized block proposal bytes
Errors: If this node is not the leader or the phase is not Propose
Cast a prevote.
pub fn prevote_native(&mut self, accept: bool) -> Result<Vec<u8>, String>Parameters:
| Parameter | Type | Description |
|---|---|---|
accept |
bool |
Whether to accept the proposal |
Returns: Serialized prevote message bytes
Cast a precommit vote.
pub fn precommit_native(&mut self, block_hash: Vec<u8>) -> Result<Vec<u8>, String>Parameters:
| Parameter | Type | Description |
|---|---|---|
block_hash |
Vec<u8> |
Hash of the block to precommit |
Returns: Serialized precommit message bytes
Process an incoming vote.
pub fn receive_vote(&mut self, vote_bytes: Vec<u8>) -> i32Parameters:
| Parameter | Type | Description |
|---|---|---|
vote_bytes |
Vec<u8> |
Serialized vote message |
Returns:
| Value | Meaning |
|---|---|
0 |
Vote accepted |
1 |
Prevote quorum reached |
2 |
Precommit quorum reached |
-1 |
Vote rejected (invalid or duplicate) |
Finalize the current round and append the block to the chain.
pub fn finalize_native(&mut self) -> Result<Vec<u8>, String>Returns: Serialized committed block bytes
Errors: If precommit quorum has not been reached
Get the current consensus state.
pub fn state(&self) -> ConsensusStatepub fn round(&self) -> u64
pub fn chain_height(&self) -> u64
pub fn threshold(&self) -> u32
pub fn prevote_count(&self) -> u32
pub fn precommit_count(&self) -> u32
pub fn latest_block_hash(&self) -> Vec<u8>
pub fn verify_chain(&self) -> boolConsensus state snapshot.
#[wasm_bindgen]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConsensusState {
pub round: u64,
pub phase: ConsensusPhase,
pub is_leader: bool,
pub prevote_count: u32,
pub precommit_count: u32,
pub chain_height: u64,
}Fields:
| Field | Type | Description |
|---|---|---|
round |
u64 |
Current consensus round |
phase |
ConsensusPhase |
Current consensus phase |
is_leader |
bool |
Whether this node is the leader |
prevote_count |
u32 |
Number of prevotes received |
precommit_count |
u32 |
Number of precommits received |
chain_height |
u64 |
Number of committed blocks |
Verify that a VRF proof is valid for leader election.
#[wasm_bindgen]
pub fn verify_leader_election(block_bytes: &[u8], tau: &[u8]) -> boolParameters:
| Parameter | Type | Description |
|---|---|---|
block_bytes |
&[u8] |
Serialized block header |
tau |
&[u8] |
32-byte VRF threshold |
Returns: true if the block's VRF proof is below the threshold
Compute the BFT quorum threshold for a given validator count.
#[wasm_bindgen]
pub fn compute_threshold(num_validators: u32) -> u32Parameters:
| Parameter | Type | Description |
|---|---|---|
num_validators |
u32 |
Number of validators |
Returns: Quorum threshold (2f + 1)
The TypeScript ConsensusEngine wraps the WASM consensus module with async methods and an event-driven interface.
Source: src/lib/consensus/consensus-engine.ts
import { ConsensusEngine } from '$lib/consensus';
const engine = new ConsensusEngine(
secretKey, // Uint8Array (32 bytes)
publicKey, // Uint8Array (32 bytes)
validators, // Uint8Array[] — list of validator public keys
config?, // ConsensusConfig (optional)
);ConsensusConfig:
interface ConsensusConfig {
tau?: Uint8Array; // 32-byte VRF threshold
checkpointInterval?: number; // VDF checkpoint interval
roundTimeoutMs?: number; // Round timeout in milliseconds (default: 30000)
}Start a new consensus round.
startRound(round: number): Uint8ArrayReturns: VRF proof bytes
Create a block proposal (leader only).
propose(vdfState: Uint8Array, timestamp: number): Uint8ArrayReturns: Serialized proposal bytes
Throws: If not the leader or not in Propose phase
Process an incoming block proposal.
receiveProposal(proposalBytes: Uint8Array): booleanReturns: true if the proposal is valid
Cast a prevote.
prevote(accept: boolean): Uint8ArrayReturns: Serialized prevote bytes
Cast a precommit vote.
precommit(blockHash: Uint8Array): Uint8ArrayReturns: Serialized precommit bytes
Process an incoming vote.
receiveVote(voteBytes: Uint8Array): numberReturns: 0 = accepted, 1 = prevote quorum, 2 = precommit quorum, -1 = rejected
Finalize the current round and commit the block.
finalize(): Uint8ArrayReturns: Serialized committed block bytes
Get the current consensus state.
getState(): ConsensusStateClean up resources and remove all event listeners.
dispose(): voidThe TypeScript ConsensusEngine extends EventEmitter and emits the following events:
| Event | Callback Signature | Description |
|---|---|---|
onPhaseChange |
(phase: ConsensusPhase) => void |
Phase transition |
onLeaderElected |
(leader: Uint8Array) => void |
Leader elected via VRF |
onProposal |
(proposal: Uint8Array) => void |
Proposal received |
onCommit |
(round: number, block: Uint8Array) => void |
Block committed |
onRoundTimeout |
(round: number) => void |
Round timed out |
onStateChange |
(state: ConsensusState) => void |
State updated |
Example:
engine.on('onCommit', (round, block) => {
console.log(`Block committed at round ${round}`);
});
engine.on('onPhaseChange', (phase) => {
console.log('Phase:', phase);
});The VotePool tracks prevotes and precommits for a consensus round.
Source: src/lib/consensus/vote-pool.ts
import { VotePool } from '$lib/consensus';
const pool = new VotePool(validatorCount: number);Parameters:
| Parameter | Type | Description |
|---|---|---|
validatorCount |
number |
Total number of validators |
Compute the BFT quorum threshold.
static computeThreshold(n: number): numberReturns: 2f + 1 where f = floor((n - 1) / 3)
Record a prevote.
addPrevote(voterPubkey: Uint8Array, blockHash: Uint8Array): booleanReturns: true if the vote was added (not a duplicate)
Record a precommit.
addPrecommit(voterPubkey: Uint8Array, blockHash: Uint8Array): booleanReturns: true if the vote was added (not a duplicate)
Check if prevote quorum is reached.
getPrevoteQuorum(): booleanCheck if precommit quorum is reached.
getPrecommitQuorum(): booleanCheck if a validator has already prevoted.
hasPrevoted(voterPubkey: Uint8Array): booleanCheck if a validator has already precommitted.
hasPrecommitted(voterPubkey: Uint8Array): booleanReset the vote pool.
clear(): void| Property | Type | Description |
|---|---|---|
prevoteCount |
number |
Number of prevotes received |
precommitCount |
number |
Number of precommits received |
quorumThreshold |
number |
Required votes for quorum |
size |
number |
Total validator count |
The BlockChain stores committed blocks and provides verification.
Source: src/lib/consensus/block-chain.ts
| Property | Type | Description |
|---|---|---|
GENESIS_HASH |
Uint8Array |
32-byte zero hash for the genesis block |
| Property | Type | Description |
|---|---|---|
height |
number |
Number of committed blocks |
latestHash |
Uint8Array |
Hash of the latest block |
latest |
BlockHeader |
Latest block header |
Append a verified block to the chain.
append(block: BlockHeader): voidThrows: If the block's prev_hash does not match latestHash
Get a block by round number.
getByRound(round: number): BlockHeader | undefinedGet a block by its hash.
getByHash(hash: Uint8Array): BlockHeader | undefinedGet the N most recent blocks.
getRecent(count: number): BlockHeader[]Verify the entire chain (hash linkage from genesis to tip).
verify(): booleanReturns: true if all blocks are valid and linked correctly
Serialize the chain to a JSON-compatible object.
toJSON(): objectThe Network API provides WebRTC peer-to-peer connectivity with a signaling server for peer discovery and SDP exchange.
The main P2P orchestrator that manages peer connections, message routing, and network state.
Source: src/lib/network/peer-manager.ts
import { PeerManager } from '$lib/network';
const manager = new PeerManager({
signalingUrl: 'wss://signal.example.com',
roomId: 'my-room',
keypair: { publicKey, secretKey },
iceServers?: [{ urls: 'stun:stun.l.google.com:19302' }],
});Connect to the signaling server and join a room.
connect(): Promise<void>Leave the room and close all peer connections.
disconnect(): voidSend a message to all connected peers.
broadcast(message: Uint8Array): voidSend a message to a specific peer.
sendTo(peerId: string, message: Uint8Array): voidGet the current network state.
getState(): NetworkStateNetworkState:
interface NetworkState {
status: 'disconnected' | 'connecting' | 'connected';
peerCount: number;
peers: Map<string, PeerInfo>;
}Get info for a specific peer.
getPeer(peerId: string): PeerInfo | undefinedGet the number of connected peers.
getPeerCount(): number| Event | Callback Signature | Description |
|---|---|---|
onPeerConnected |
(peerId: string) => void |
Peer connection established |
onPeerDisconnected |
(peerId: string) => void |
Peer disconnected |
onMessage |
(peerId: string, data: Uint8Array) => void |
Message received from peer |
onStateChange |
(state: NetworkState) => void |
Network state changed |
A WebRTC wrapper for a single peer-to-peer connection.
Source: src/lib/network/peer-connection.ts
- IPv6-prioritized ICE candidate handling
- DataChannel management with ordered/unordered modes
- Ping/pong RTT measurement
- Automatic reconnection support
Create an SDP offer for this connection.
createOffer(): Promise<RTCSessionDescriptionInit>Process an incoming SDP offer and generate an answer.
handleOffer(offer: RTCSessionDescriptionInit): Promise<RTCSessionDescriptionInit>Process an incoming SDP answer.
handleAnswer(answer: RTCSessionDescriptionInit): Promise<void>Add an ICE candidate to the connection.
addIceCandidate(candidate: RTCIceCandidateInit): Promise<void>Send data over the DataChannel.
send(data: Uint8Array): voidClose the connection and all associated channels.
close(): voidGet connection info including RTT and state.
getInfo(): PeerInfoPeerInfo:
interface PeerInfo {
peerId: string;
rtt: number; // Round-trip time in ms
state: RTCPeerConnectionState;
connectedAt: number; // Unix timestamp
}WebSocket client for the Cloudflare Durable Object signaling server.
Source: src/lib/network/signaling-client.ts
- Cloudflare Durable Object signaling protocol
- Auto-reconnect with exponential backoff
- Room-based peer discovery
Connect to the signaling server and join a room.
connect(roomId: string): Promise<void>Leave the room and close the WebSocket.
disconnect(): voidSend an SDP offer to a specific peer via signaling.
sendOffer(peerId: string, offer: RTCSessionDescriptionInit): voidSend an SDP answer to a specific peer via signaling.
sendAnswer(peerId: string, answer: RTCSessionDescriptionInit): voidSend an ICE candidate to a specific peer via signaling.
sendCandidate(peerId: string, candidate: RTCIceCandidateInit): voidLeave the current room.
leave(): voidProtobuf-based binary message encoder/decoder for network messages.
Source: src/lib/network/message-codec.ts
Initialize the message codec with the protobuf module.
import { initCodec, MessageCodec } from '$lib/network/message-codec';
await initCodec();Note: Must be called once before using MessageCodec. Loads the generated protobuf definitions.
Static encode/decode utility for network messages.
class MessageCodec {
static encode(message: NetworkMessage): Uint8Array;
static decode(data: Uint8Array): NetworkMessage;
}Encode a message to binary.
static encode(message: NetworkMessage): Uint8ArrayDecode a binary message.
static decode(data: Uint8Array): NetworkMessagetype NetworkMessage =
| PingMessage
| PongMessage
| CheckpointMessage
| WinnerMessage
| PeerDiscoveryMessage
| VdfProgressMessage
| ConsensusProposalMessage
| ConsensusVoteMessage
| NewRoundMessage;| Type | Description |
|---|---|
ping |
Keep-alive ping |
pong |
Keep-alive pong response |
checkpoint |
VDF checkpoint data |
winner |
VRF winner announcement |
peer-discovery |
Peer list update |
vdf-progress |
VDF computation progress |
consensus-proposal |
Block proposal broadcast |
consensus-vote |
Prevote/precommit broadcast |
new-round |
New round announcement |
Helper functions for creating consensus-related network messages.
Source: src/lib/network/message-codec.ts
Create a consensus proposal message for broadcast.
function createConsensusProposal(
round: number,
vdfState: Uint8Array,
vrfProof: Uint8Array,
blockHash: Uint8Array,
prevBlockHash: Uint8Array,
timestamp: number
): ConsensusProposalMessage;Parameters:
| Parameter | Type | Description |
|---|---|---|
round |
number |
Consensus round number |
vdfState |
Uint8Array |
VDF state at proposal time |
vrfProof |
Uint8Array |
VRF proof of leader election |
blockHash |
Uint8Array |
Hash of the proposed block |
prevBlockHash |
Uint8Array |
Hash of the previous block |
timestamp |
number |
Proposal timestamp (Unix ms) |
Create a consensus vote message (prevote or precommit).
function createConsensusVote(
round: number,
phase: 'prevote' | 'precommit',
blockHash: Uint8Array,
voterPubkey: Uint8Array
): ConsensusVoteMessage;Parameters:
| Parameter | Type | Description |
|---|---|---|
round |
number |
Consensus round number |
phase |
'prevote' | 'precommit' |
Vote phase |
blockHash |
Uint8Array |
Hash being voted on |
voterPubkey |
Uint8Array |
Voter's public key |
Create a new round announcement message.
function createNewRound(round: number, seed: Uint8Array, validators: Uint8Array[]): NewRoundMessage;Parameters:
| Parameter | Type | Description |
|---|---|---|
round |
number |
New round number |
seed |
Uint8Array |
Round seed (from previous block hash) |
validators |
Uint8Array[] |
Validator set for the new round |
The Web Worker runs VDF computation in the background and communicates with the main thread via messages.
Start VDF computation.
interface StartMessage {
type: 'start';
seed: Uint8Array; // 32-byte seed
total: number; // Total steps
k: number; // VRF sampling interval
tau: Uint8Array; // 32-byte threshold
checkpointInterval: number; // Checkpoint interval
}Example:
worker.postMessage({
type: 'start',
seed: new Uint8Array(32),
total: 1000000,
k: 1000,
tau: new Uint8Array(32),
checkpointInterval: 100000
});Pause computation.
interface PauseMessage {
type: 'pause';
}Example:
worker.postMessage({ type: 'pause' });Resume computation.
interface ResumeMessage {
type: 'resume';
}Example:
worker.postMessage({ type: 'resume' });Stop computation.
interface StopMessage {
type: 'stop';
}Example:
worker.postMessage({ type: 'stop' });Computation started successfully.
interface StartedMessage {
type: 'started';
publicKey: Uint8Array; // Node's VRF public key
}Progress update (sent every second).
interface ProgressMessage {
type: 'progress';
step: number; // Current step
speed: number; // Steps per second
memoryUsage: number; // Memory usage in bytes
}VRF winner found.
interface WinnerMessage {
type: 'winner';
step: number; // Winner step
proof: Uint8Array; // VRF proof
}Computation finished.
interface FinishedMessage {
type: 'finished';
step: number; // Final step
}Keep-alive signal (sent every 10 seconds).
interface HeartbeatMessage {
type: 'heartbeat';
timestamp: number; // Unix timestamp (ms)
status: string; // 'running' | 'paused'
}Error occurred.
interface ErrorMessage {
type: 'error';
code: string; // Error code
message: string; // Error description
recoverable: boolean; // Whether error is recoverable
}type WorkerMessage = StartMessage | PauseMessage | ResumeMessage | StopMessage;
type WorkerResponse =
| StartedMessage
| ProgressMessage
| WinnerMessage
| FinishedMessage
| HeartbeatMessage
| ErrorMessage;Reactive store for worker state.
import { workerState } from '$stores/worker';
// Subscribe to changes
workerState.subscribe((state) => {
console.log('Is running:', state.isRunning);
console.log('Current step:', state.currentStep);
});interface WorkerState {
isRunning: boolean; // Whether computation is running
isPaused: boolean; // Whether computation is paused
currentStep: number; // Current VDF step
totalSteps: number; // Total steps target
speed: number; // Current speed (steps/sec)
uptime: number; // Uptime in seconds
winnerCount: number; // Number of winners found
luckPercentage: number; // Luck percentage
publicKey: Uint8Array | null; // Node's public key
nodeId: string; // Node identifier
}Store for event log.
import { events } from '$stores/worker';
// Subscribe to events
events.subscribe((eventList) => {
console.log('Events:', eventList);
});interface VtpEvent {
type: 'info' | 'checkpoint' | 'winner' | 'error';
timestamp: number; // Unix timestamp (ms)
message: string; // Event message
}Derived store for progress percentage.
import { progress } from '$stores/worker';
// Subscribe to progress
progress.subscribe((value) => {
console.log('Progress:', (value * 100).toFixed(1) + '%');
});Type: Readable<number> (0 to 1)
Add event to event log.
function addEvent(event: Omit<VtpEvent, 'timestamp'>): void;Parameters:
| Parameter | Type | Description |
|---|---|---|
event |
Omit<VtpEvent, 'timestamp'> |
Event without timestamp |
Example:
addEvent({ type: 'info', message: 'Computation started' });
addEvent({ type: 'winner', message: '🎉 Winner at step 12345' });Reset worker state to initial values.
function resetWorkerState(): void;Example:
resetWorkerState();Format bytes to human-readable string.
function formatBytes(bytes: number): string;Example:
formatBytes(0); // "0 B"
formatBytes(1024); // "1 KB"
formatBytes(1048576); // "1 MB"Format number with locale-specific separators.
function formatNumber(num: number): string;Example:
formatNumber(1234567); // "1,234,567"Format speed value.
function formatSpeed(speed: number): string;Example:
formatSpeed(1500000); // "1.5M"
formatSpeed(1500); // "1.5K"
formatSpeed(500); // "500"Format seconds to HH:MM:SS.
function formatTime(seconds: number): string;Example:
formatTime(0); // "00:00:00"
formatTime(61); // "00:01:01"
formatTime(3661); // "01:01:01"Generate 8-character hex node ID.
function generateNodeId(): string;Example:
generateNodeId(); // "a1b2c3d4"Note: Uses Math.random(), not cryptographically secure
Async sleep function.
function sleep(ms: number): Promise<void>;Example:
async function example() {
console.log('Start');
await sleep(1000);
console.log('End');
}Create debounced function.
function debounce<T extends (...args: any[]) => any>(
func: T,
wait: number
): (...args: Parameters<T>) => void;Example:
const debouncedSearch = debounce((query: string) => {
console.log('Searching:', query);
}, 300);
debouncedSearch('a');
debouncedSearch('ab');
debouncedSearch('abc');
// Only 'abc' will be logged after 300ms// Main Thread → Worker
interface WorkerMessage {
type: string;
seed?: Uint8Array;
total?: number;
k?: number;
tau?: Uint8Array;
checkpointInterval?: number;
maxSteps?: number;
}
// Worker → Main Thread
interface ProgressMessage {
type: 'progress';
step: number;
speed: number;
memoryUsage: number;
}
interface WinnerMessage {
type: 'winner';
step: number;
proof: Uint8Array;
}
interface HeartbeatMessage {
type: 'heartbeat';
timestamp: number;
status: string;
}
interface ErrorMessage {
type: 'error';
code: string;
message: string;
recoverable: boolean;
}
interface StartedMessage {
type: 'started';
publicKey: Uint8Array;
}
interface StoppedMessage {
type: 'stopped';
}
interface FinishedMessage {
type: 'finished';
step: number;
}
type WorkerResponse =
| ProgressMessage
| WinnerMessage
| HeartbeatMessage
| ErrorMessage
| StartedMessage
| StoppedMessage
| FinishedMessage;| Code | Description | Recoverable |
|---|---|---|
UNKNOWN_COMMAND |
Unknown command received | No |
INVALID_PARAMS |
Missing or invalid parameters | No |
INIT_FAILED |
Session initialization failed | Yes |
COMPUTATION_ERROR |
Error during computation | Yes |
VDF_ERROR |
VDF computation error | Yes |
// 1. Create worker
const worker = new Worker(new URL('$lib/worker/index.ts', import.meta.url), {
type: 'module'
});
// 2. Listen for messages
worker.onmessage = (event) => {
const msg = event.data;
switch (msg.type) {
case 'progress':
console.log(`Step: ${msg.step}, Speed: ${msg.speed}`);
break;
case 'winner':
console.log(`Winner at step ${msg.step}`);
break;
case 'error':
console.error(`Error: ${msg.message}`);
break;
}
};
// 3. Start computation
worker.postMessage({
type: 'start',
seed: new Uint8Array(32),
total: 1000000,
k: 1000,
tau: new Uint8Array(32),
checkpointInterval: 100000
});
// 4. Pause after 10 seconds
setTimeout(() => {
worker.postMessage({ type: 'pause' });
}, 10000);
// 5. Resume after 5 seconds
setTimeout(() => {
worker.postMessage({ type: 'resume' });
}, 15000);
// 6. Stop after 1 minute
setTimeout(() => {
worker.postMessage({ type: 'stop' });
worker.terminate();
}, 60000);<script lang="ts">
import { workerState, events, addEvent, resetWorkerState } from '$stores/worker';
// Subscribe to state changes
$: {
if ($workerState.isRunning) {
console.log('Running at speed:', $workerState.speed);
}
}
// Add event
function handleWinner() {
addEvent({ type: 'winner', message: '🎉 Winner found!' });
}
// Reset state
function handleReset() {
resetWorkerState();
}
</script>
<div>
<p>Speed: {$workerState.speed} steps/sec</p>
<p>Progress: {$workerState.currentStep} / {$workerState.totalSteps}</p>
{#each $events as event}
<p>{event.message}</p>
{/each}
</div>// Consensus round lifecycle
import { ConsensusEngine } from '$lib/consensus';
const engine = new ConsensusEngine(secretKey, publicKey, validators, {
tau: new Uint8Array(32).fill(0xff),
checkpointInterval: 1000,
roundTimeoutMs: 30_000
});
engine.on('onCommit', (round, block) => {
console.log(`Block finalized at round ${round}`);
});
// Start round
const vrfProof = engine.startRound(1);
if (engine.isLeader) {
const proposal = engine.propose(vdfState, Date.now());
// broadcast proposal
} else {
// wait for proposal, validate, vote
}For API questions or issues:
- GitHub Issues: Create an issue
- Email: api@vtp-node.dev