Skip to content

Fiono11/threshold_stellar

Repository files navigation

Decentralized Threshold Signing Service

Overview

This project implements a decentralized threshold signing service leveraging the Olaf protocol. The service operates off-chain, providing a secure and cost-effective alternative to on-chain threshold signature mechanisms within the Stellar ecosystem.

Each participant in the threshold signing group runs a browser-based application that performs decentralized key generation and signing operations through the Olaf threshold signature protocol, compiled to WebAssembly (WASM). The networking layer is built using JavaScript and libp2p for peer discovery and communication.

The service implements proof of possession mechanisms to ensure that only the legitimate owner of a Stellar address can register it with the relay server and establish connections with other peers. This prevents address spoofing and ensures secure peer-to-peer communication.

🌐 Networking Layer (JavaScript)

Transport: Peers connect to a relay server using WebSockets.

Discovery:

  • When a peer connects, it must prove ownership of its Stellar address through a cryptographic challenge-response protocol
  • The peer requests a challenge from the relay server, signs it with their private key, and submits the proof
  • The relay server verifies the signature using the address's public key and stores the mapping: Address β†’ Peer ID
  • Peers can query the relay server with a known Stellar address to obtain the corresponding Peer ID

Direct Peer Communication: Once a Peer ID is obtained, the peer establishes a WebRTC connection using libp2p. Before communication begins, both peers perform mutual proof of possession to verify each other's identity. All protocol messages are exchanged via this secure, direct P2P channel.

πŸ” Cryptographic Protocol (Rust β†’ WASM)

The cryptographic logic is written in Rust and compiled to WebAssembly (WASM) for browser use.

Core Functionality:

  • Distributed Key Generation (DKG) to derive a shared threshold public key
  • Threshold Signing for signing Stellar transactions

State Management: Key shares and protocol state are stored in browser-local storage (e.g., IndexedDB).

πŸ”’ Security Features

The service implements proof of possession mechanisms to ensure secure peer-to-peer communication and prevent address spoofing attacks.

Address Registration Proof of Possession

When a peer registers their Stellar address with the relay server:

  1. Challenge Generation: The peer requests a cryptographic challenge from the relay server
  2. Challenge Signing: The peer signs the challenge using their private key corresponding to the Stellar address
  3. Signature Verification: The relay server verifies the signature using the address's public key
  4. Registration: Only upon successful verification is the address registered and mapped to a Peer ID

This ensures that only the legitimate owner of a Stellar address can register it with the relay server.

Connection Proof of Possession

When two peers establish a direct connection:

  1. Initiator Challenge: The connecting peer requests a challenge from the target peer
  2. Initiator Response: The connecting peer signs the challenge and sends their response
  3. Mutual Challenge: The target peer generates their own challenge for the initiator
  4. Mutual Verification: Both peers verify each other's signatures
  5. Connection Established: Only after mutual verification is the connection considered secure

This mutual verification process ensures that both parties can confirm each other's identity before any sensitive protocol messages are exchanged.

Cryptographic Implementation

  • Signature Algorithm: Uses Ed25519 signatures for compatibility with Stellar
  • Challenge Format: Random 32-byte challenges generated using cryptographically secure random number generation
  • Signature Verification: Leverages the stellar-base library for signature verification
  • Expiration: Challenges expire after 5 minutes to prevent replay attacks

Development Status

βœ… Milestone 1: Peer Discovery via Blockchain Address (COMPLETED)

This milestone establishes the foundational networking layer where two browsers can connect to a relay server, register with a Stellar address, discover each other, and exchange messages directly over WebRTC using libp2p.

Completed Features:

  • βœ… LibP2P relay server with WebSocket transport
  • βœ… Peer discovery system using Stellar addresses with proof of possession
  • βœ… Cryptographic challenge-response protocol for address registration
  • βœ… Address β†’ Peer ID mapping and storage in relay server with verification
  • βœ… Browser-based LibP2P client with WebRTC transport
  • βœ… Direct peer communication via WebRTC using libp2p
  • βœ… Mutual proof of possession for peer-to-peer connections
  • βœ… Peer-to-peer message exchange protocol with identity verification
  • βœ… Docker containerization for relay server and client
  • βœ… Comprehensive automated tests using Playwright
  • βœ… Inline documentation and testing guide

🚧 Milestone 2: Distributed Key Generation (PLANNED)

Two browsers will exchange messages and successfully produce a shared threshold public key using the Olaf DKG protocol compiled to WASM.

Planned Deliverables:

  • Rust to WebAssembly compilation of Olaf DKG protocol
  • Integration of DKG protocol with browser client
  • Shared threshold public key generation
  • Browser-local storage for key shares and protocol state

🚧 Milestone 3: Threshold Signature (PLANNED)

Two browsers will exchange messages and produce a valid threshold signature over a given Stellar transaction using the Olaf protocol compiled to WASM.

Planned Deliverables:

  • Threshold signature generation for Stellar transactions
  • Complete tutorial and article explaining the service
  • Production-ready implementation

Build and Testing

Without Docker

Prerequisites

  • Node.js installed
  • npm or yarn package manager

Automatic Testing

npm test

Manual Testing

  1. Start the relay server:

    npm run relay
  2. Start the first client application on port 5173:

    npm start
  3. Start the second client application on port 5174 (in a new terminal):

    npm start
  4. Follow the manual testing steps below (same process for both Docker and non-Docker)

With Docker

Prerequisites

  • Docker and Docker Compose installed

Docker Services

This project provides four Docker services:

  1. relay-server - The LibP2P relay server

    • Runs on port 8080
    • Handles peer discovery and key-value storage
    • Must be started before the clients
  2. client-a - The first client server

    • Runs on port 5173
    • Serves the browser-based client application for the first participant
    • Depends on the relay server being available
  3. client-b - The second client server

    • Runs on port 5174
    • Serves the browser-based client application for the second participant
    • Depends on the relay server being available
  4. test - The automated test runner

    • Uses Playwright for browser automation
    • Runs integration tests against the relay and client services
    • Exits after test completion

Docker Setup

Before running the test scenario, ensure Docker is properly set up:

  1. Install Docker Desktop:

  2. Start Docker Desktop:

    • On macOS: Open Docker Desktop from Applications folder or run open -a Docker command from the terminal
    • On Windows: Start Docker Desktop from Start menu
    • On Linux: Start Docker daemon: sudo systemctl start docker
  3. Verify Docker is running:

    docker ps

    You should see Docker version information and an empty container list.

Automatic Testing

npm run test:docker

Manual Testing

Start the relay-server and the two clients:

docker compose up -d

Manual Testing Steps (Same for Both Docker and Non-Docker)

  1. Open the first browser window/tab:

    • Navigate to http://localhost:5173
    • Wait for the "Connected to relay" message
    • In the "Stellar Address" input field, enter a Stellar address. For example: GDHMW6QZOL73SHKG2JG4MFD7X5Z6Y6Q67H5OONPKUQYRCHCLKGT5BAJZ
    • In the "Secret Key" input field, enter the corresponding secret key (Stellar format starting with S, or hex 32 bytes). For example: SDVX4LJGH7FJ5RLYMXKQTKG3G4NZ2F7A3BW3NV6HS4LQMQI6EQN6Z2QF
    • Click "Store Stellar Address with Proof of Possession"
    • Verify you see: "Address registered with proof of possession!"
  2. Open a second browser window/tab:

    • Navigate to http://localhost:5174
    • Wait for the "Connected to relay" message
    • In the "Stellar Address" input field, enter a Stellar address. For example: GBQNR2WMGKP45RIKZTJLGKDT4OHK5CQFRR5FUIZQMQVWYFB4UI5JJM2V
    • In the "Secret Key" input field, enter the corresponding secret key (Stellar format starting with S, or hex 32 bytes). For example: SC4VZJFT3QKBCFROB6GGQCH6S27ECEGQMK5XQHY6JJNQQ6QQH25HN2Z4
    • Click "Store Stellar Address with Proof of Possession"
    • Verify you see: "Address registered with proof of possession!"
  3. Connect to the first peer (in the second browser):

    • In the "Stellar Address" input field, enter: GDHMW6QZOL73SHKG2JG4MFD7X5Z6Y6Q67H5OONPKUQYRCHCLKGT5BAJZ
    • Click "Find Peer & Connect"
    • Wait for the other peer to accept the connection
  4. Accept the connection (in the first browser):

    • In the first browser window, you should see a connection permission request
    • Click "Accept" to allow the connection
  5. Autenticate the connection:

    • Verify you see the message "Mutual connection proof of possession completed!" or "Mutual connection challenge verified - connection established!"
    • Both browser windows should show the peer connection in "Active Connections"
    • The "Message" section should now be visible in both windows
  6. Send a message from the first browser:

    • In the first browser window, type a message in the "Message" field
    • Click "Send"
    • Verify the message is received in the second browser window
  7. Send a message from the second browser:

    • In the second browser window, type a different message
    • Click "Send"
    • Verify the message is received in first browser window
  8. Shutdown the relay server:

    • Ctrl+C in the relay server terminal (non Docker) or docker compose stop relay-server
    • Verify that both peers are still able to exchange messages

Cleanup

Docker Cleanup

docker compose down --rmi all --volumes --remove-orphans

Non-Docker Cleanup

Simply stop the processes with Ctrl+C in the terminal windows where they are running.

License

This project is licensed under the GPLv3 License - see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published