gsio-net
gsio-net is a distributed ledger system with three main components:
- gsio-node: A Rust-based Socket.IO server that handles real-time communication
- gsio-relay: A Rust-based WebSocket server implemented as a Cloudflare Worker
- gsio-node-client: A TypeScript client for connecting to the gsio-node server
Project Overview
gsio-net
provides a foundation for building distributed ledger applications with real-time communication capabilities. The system uses Socket.IO for client-server communication and WebSockets for peer-to-peer relay.
Project Status
Why it exists
- 1 AM couch spark → next-morning code.
- Big idea: a multipurpose private network—built only with open-web tech—that gives any group trust (tamper-proof), transparency (everyone can verify), and anonymity (no personal data needed).
What works today
- Real-time sync – add a note on one computer, see it on every other in under a second.
- Cryptographic chain – each note is linked to the last, so history can't be secretly edited.
- Auto-peer discovery – nodes find each other through a tiny Cloudflare Worker relay.
- Runs almost anywhere – thanks to Socket.IO (via Rust crate
socketoxide
) which swaps between WebSockets, HTTP long-polling, etc., to punch through most firewalls.
What's next
- Direct peer-to-peer connections with iroh
- When a node or client first connects, it will generate an iroh dial-out address (think of it as its "phone number").
- That address is broadcast over the existing Socket.IO channel.
- Other peers will then call that number to form a direct, encrypted link—skipping the relay for faster, more private transfers.
- A slick web UI so non-coders can join with one click.
- One-command deploy scripts so anyone can spin up their own private micro-network.
- A visual history viewer that shows who posted what (optionally under nicknames).
Key Features
- Distributed ledger with cryptographic verification
- Peer-to-peer networking with node discovery and message propagation
- Consensus mechanism for ledger synchronization
- Real-time bidirectional communication using Socket.IO
- WebSocket relay for peer-to-peer messaging
- TypeScript client for easy integration with web applications
- Rust-based servers for high performance and reliability
Network Architecture
gsio-net
implements a hybrid network architecture combining client-server and peer-to-peer models:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ gsio-node │◄────┤ gsio-relay │◄────│ gsio-node │
│ (Server A) │ │ (WebSocket │ │ (Server B) │
└──────┬──────┘ │ Relay) │ └──────┬──────┘
│ └─────────────┘ │
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ gsio-client │ │ gsio-client │
│ (Client A) │ │ (Client B) │
└─────────────┘ └─────────────┘
How the Network Works
-
Node-Client Communication:
- Clients connect to gsio-node servers using Socket.IO
- Each server maintains its own distributed ledger
- Clients can add entries to the ledger and retrieve ledger data
-
Node-Node Communication:
- Nodes communicate with each other through the gsio-relay server
- The relay server acts as a message broker using WebSockets
- Nodes can discover each other and synchronize their ledgers
-
Distributed Ledger:
- Each ledger entry contains data, timestamps, and cryptographic hashes
- Entries form a chain where each entry references the previous entry's hash
- The ledger is synchronized across nodes using the P2P network
-
Message Flow:
- When a client adds an entry to a node's ledger, the node broadcasts it to other nodes
- Nodes validate incoming entries and add them to their ledgers
- Nodes can request missing entries from other nodes to maintain synchronization
Protocol Details
The P2P protocol uses the following message types:
-
NodeAnnounce: Announces a new node joining the network. Empty recipient_id indicates a broadcast message.
{ "message_type": "NodeAnnounce", "message_id": "uuid-string", "sender_id": "node-id", "recipient_id": "", "payload": { "node_id": "node-id" } }
-
NodeListRequest/Response: Request and response for the list of known nodes
{ "message_type": "NodeListResponse", "message_id": "uuid-string", "sender_id": "node-id", "recipient_id": "requesting-node-id", "payload": { "nodes": ["node-id-1", "node-id-2"] } }
-
EntryAnnounce: Announces a new ledger entry. Empty recipient_id indicates a broadcast message.
{ "message_type": "EntryAnnounce", "message_id": "uuid-string", "sender_id": "node-id", "recipient_id": "", "payload": { "id": "entry-id", "timestamp": "2023-05-20T15:30:45Z", "data": { "message": "Example data" }, "previous_hash": "hash-string", "hash": "hash-string", "creator_node_id": "node-id", "signatures": {} } }
-
LedgerSyncRequest/Response: Request and response for synchronizing the entire ledger. The payload contains an array of ledger entries.
{ "message_type": "LedgerSyncResponse", "message_id": "uuid-string", "sender_id": "node-id", "recipient_id": "requesting-node-id", "payload": [] }
Security Considerations
-
Cryptographic Verification:
- Each ledger entry is hashed using SHA-256
- The hash includes the entry's ID, timestamp, data, previous hash, and creator node ID
- This ensures the integrity of the ledger chain
-
Chain Integrity:
- Each entry references the hash of the previous entry
- This creates a cryptographic chain that is difficult to tamper with
- Nodes validate the hash of each entry before adding it to their ledger
-
Consensus Mechanism:
- Entries are ordered by timestamp to ensure deterministic ordering
- Nodes only accept entries that link to their current last entry
- This ensures that all nodes converge to the same ledger state
-
Authentication:
- The current implementation uses simple node IDs
- For production use, implement proper authentication and authorization
- Consider adding digital signatures for entry validation
Getting Started
Prerequisites
- Rust (latest stable version)
- Node.js (latest LTS version)
- Bun (for running TypeScript code and tests)
- Wrangler CLI (for Cloudflare Workers development)
Installation
-
Clone the repository:
git clone https://github.com/seemueller-io/gsio-net.git cd gsio-net
-
Install dependencies:
npm install
This will also build the Rust components due to the
postinstall
script.
Running the Components
-
gsio-node (Socket.IO server):
cd crates/gsio-node cargo run
The server will start on port 3000. Each node has a unique ID and maintains its own distributed ledger.
-
gsio-relay (WebSocket relay):
cd crates/gsio-relay wrangler dev
The WebSocket server will start on port 8787. This relay enables p2p communication between nodes.
-
gsio-node-client (Socket.IO client):
cd packages/gsio-node-client bun src/listeners/node_listener.ts
This will connect to the gsio-node server and interact with the distributed ledger.
-
gsio-node-client (WebSocket p2p client):
cd packages/gsio-node-client bun src/listeners/ws_client.ts
This will connect to the relay server and participate in the p2p network.
Using the Distributed Ledger
The Socket.IO client provides the following functions for interacting with the distributed ledger:
-
Adding an entry:
// Add a new entry to the ledger socket.emit("add_ledger_entry", { message: "Hello, ledger!", timestamp: new Date().toISOString() });
-
Getting all entries:
// Request all ledger entries socket.emit("get_ledger"); // Handle the response socket.on("ledger_entries", (entries) => { console.log("Ledger entries:", entries); });
-
Getting known nodes:
// Request all known nodes socket.emit("get_known_nodes"); // Handle the response socket.on("known_nodes", (data) => { console.log("Known nodes:", data.nodes); });
Using the P2P Network
The WebSocket client provides the following functions for participating in the p2p network:
-
Sending a p2p message:
// Send a p2p message sendP2PMessage({ message_type: "NodeAnnounce", sender_id: nodeId, recipient_id: "", payload: { node_id: nodeId } });
-
Handling p2p messages:
// Handle incoming p2p messages websocket.addEventListener("message", (event) => { const message = JSON.parse(event.data); console.log("Received p2p message:", message); });
Development
Project Structure
- crates/: Contains Rust crates
- gsio-node/: Socket.IO server implementation
- src/ledger.rs: Distributed ledger implementation
- src/p2p.rs: Peer-to-peer networking implementation
- gsio-relay/: WebSocket server implemented as a Cloudflare Worker
- gsio-node/: Socket.IO server implementation
- packages/: Contains TypeScript packages
- gsio-node-client/: Client for connecting to the gsio-node server
- src/listeners/node_listener.ts: Socket.IO client for ledger operations
- src/listeners/ws_client.ts: WebSocket client for p2p communication
- scripts/: Utility scripts for the project
- gsio-node-client/: Client for connecting to the gsio-node server
Distributed Ledger
The distributed ledger is implemented in crates/gsio-node/src/ledger.rs
and provides the following features:
- Ledger Entries: Each entry contains data, timestamps, and cryptographic hashes
- Chain Integrity: Each entry references the hash of the previous entry
- Validation: Entries are validated using cryptographic hashes
- Consensus: Entries are synchronized across nodes in the network
Peer-to-Peer Networking
The p2p networking is implemented in crates/gsio-node/src/p2p.rs
and provides the following features:
- Node Discovery: Nodes announce themselves to the network
- Message Propagation: Messages are propagated to all connected nodes
- Connection Management: Connections are managed using Socket.IO
- Ledger Synchronization: Nodes can request and receive ledger entries from other nodes
Building Individual Components
-
gsio-node:
cd crates/gsio-node cargo build
-
gsio-relay:
cd crates/gsio-relay cargo install -q worker-build && worker-build --release
-
gsio-node-client:
cd packages/gsio-node-client bun install
Running Tests
-
Rust Tests:
cd crates/gsio-node cargo test
-
TypeScript Tests:
cd packages/gsio-node-client bun test
Debugging
- gsio-node: Use
RUST_LOG=debug cargo run
for verbose logging. - gsio-relay: Use
wrangler dev --verbose
for detailed logs. - gsio-node-client: Add
console.log
statements for debugging.
Cleaning the Project
To clean the project, run:
npm run clean
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.