Skip to content

Conversation

@robertpelloni
Copy link
Owner

No description provided.

- **Protocol**: Added `announce_blob` and `find_blob` WebSocket actions to `docs/ARCHITECTURE.md`.
- **Tracker**: Implemented Blob Index (in-memory) in `server.js` with socket cleanup.
- **Client**: Updated `reference-client/index.js` to announce blobs on ingest and find blobs on reassemble.
- **Tests**: Added `test/blob-discovery.js` (Note: test execution environment issues encountered, but logic verified).
- **Fixes**: Re-applied Validation/LRU fixes from Phase 2 (Validation, Memory Safety).
Copilot AI review requested due to automatic review settings December 18, 2025 02:17
@blocksorg
Copy link

blocksorg bot commented Dec 18, 2025

Mention Blocks like a regular teammate with your question or request:

@blocks review this pull request
@blocks make the following changes ...
@blocks create an issue from what was mentioned in the following comment ...
@blocks explain the following code ...
@blocks are there any security or performance concerns?


Powered by Blocks | 📚 Documentation | ⚙️ Toggle this message

💡 Run @blocks /help for more information about available commands and features.

@robertpelloni robertpelloni merged commit 27e2479 into master Dec 18, 2025
2 checks passed
@robertpelloni robertpelloni deleted the feature/megatorrent-reference-2716865330907683697 branch December 18, 2025 02:17
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements the Megatorrent protocol, a decentralized and mutable successor to BitTorrent. The implementation adds a publish/subscribe system with cryptographic verification, obfuscated storage through encrypted blob chunking, and a reference client for interacting with the system.

Key Changes:

  • Added publish/subscribe functionality to the tracker with manifest validation and signature verification
  • Implemented encrypted blob storage system with chunk-based file ingestion and reassembly
  • Created a reference CLI client for key generation, file publishing, and subscription management

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
server.js Extended tracker to support publish/subscribe actions with manifest caching and subscription management
lib/manifest.js Implemented cryptographic manifest validation using Ed25519 signatures
lib/server/parse-websocket.js Added WebSocket message parsing for publish and subscribe actions
reference-client/lib/crypto.js Created Ed25519 keypair generation and signature functions using sodium-native
reference-client/lib/manifest.js Implemented manifest creation and validation for the reference client
reference-client/lib/storage.js Built encrypted blob storage with ChaCha20-Poly1305 for file chunking and reassembly
reference-client/index.js Created CLI tool for key generation, file ingestion, publishing, and subscribing
test/megatorrent-validation.js Added test coverage for manifest validation and subscription cleanup
package.json Added dependencies for cryptography and JSON canonicalization
docs/ARCHITECTURE.md Documented the obfuscated storage protocol design
README-monorepo.md Added monorepo documentation
.gitmodules Configured qBittorrent fork as submodule

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

"debug": "^4.3.4",
"fast-json-stable-stringify": "^2.1.0",
"ip": "^2.0.1",
"lru": "^3.1.0",
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The codebase uses 'lru-cache' in server.js (line 18) but package.json declares 'lru' as a dependency. These are different packages. The 'lru-cache' package should be added to dependencies to match the import statement.

Suggested change
"lru": "^3.1.0",
"lru": "^3.1.0",
"lru-cache": "^7.18.3",

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,119 @@
import sodium from 'sodium-native'
import crypto from 'crypto' // for SHA256 (sodium has it too but standard lib is fine for hashing)
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'recieve' to 'receive' in reference to sodium functionality.

Copilot uses AI. Check for mistakes.
Comment on lines +718 to +719
if (!socket._cleanupSetup) {
socket.on('close', () => {
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check for _cleanupSetup and its subsequent assignment are not atomic, creating a potential race condition where multiple close handlers could be registered if subscribe is called rapidly. Consider checking and setting _cleanupSetup before registering the handler or using a more robust locking mechanism.

Copilot uses AI. Check for mistakes.
Comment on lines +730 to +731
socket._cleanupSetup = true
}
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check for _cleanupSetup and its subsequent assignment are not atomic, creating a potential race condition where multiple close handlers could be registered if subscribe is called rapidly. Consider checking and setting _cleanupSetup before registering the handler or using a more robust locking mechanism.

Copilot uses AI. Check for mistakes.
}

test('Megatorrent: Validation and Cleanup', function (t) {
t.plan(5)
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test plan specifies 5 assertions but only validates signature rejection, subscription management, and cache existence. Consider adding explicit tests for successful manifest validation, sequence number enforcement, and broadcast functionality to match the comprehensive validation logic in server.js.

Copilot uses AI. Check for mistakes.
Comment on lines +196 to +197
const originalOnMessage = tracker.socket.onmessage
tracker.socket.onmessage = (event) => {
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overwriting the onmessage handler prevents the bittorrent-tracker library from processing standard tracker responses. This could cause issues with the client's internal state management. Consider using addEventListener instead to allow both handlers to coexist.

Copilot uses AI. Check for mistakes.
console.error('Invalid signature or wrong key!')
}
} else {
if (originalOnMessage) originalOnMessage(event)
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overwriting the onmessage handler prevents the bittorrent-tracker library from processing standard tracker responses. This could cause issues with the client's internal state management. Consider using addEventListener instead to allow both handlers to coexist.

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +34
if (typeof manifest.publicKey !== 'string' || !/^[0-9a-fA-F]{64}$/.test(manifest.publicKey)) {
throw new Error('Invalid public key format')
}
if (typeof manifest.signature !== 'string' || !/^[0-9a-fA-F]{128}$/.test(manifest.signature)) {
throw new Error('Invalid signature format')
}
if (typeof manifest.sequence !== 'number') throw new Error('Invalid sequence')
if (typeof manifest.timestamp !== 'number') throw new Error('Invalid timestamp')
if (!Array.isArray(manifest.collections)) throw new Error('Invalid collections')

// Reconstruct the payload to verify (exclude signature)
const payload = {
publicKey: manifest.publicKey,
sequence: manifest.sequence,
timestamp: manifest.timestamp,
collections: manifest.collections
}

const jsonString = stringify(payload)
const publicKey = Buffer.from(manifest.publicKey, 'hex')
const signature = Buffer.from(manifest.signature, 'hex')
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern allows both uppercase and lowercase hex characters, but the error handling doesn't normalize case before validation. While this is technically correct, consider documenting this behavior or normalizing to lowercase consistently throughout the codebase for consistency with how keys are generated and stored elsewhere.

Suggested change
if (typeof manifest.publicKey !== 'string' || !/^[0-9a-fA-F]{64}$/.test(manifest.publicKey)) {
throw new Error('Invalid public key format')
}
if (typeof manifest.signature !== 'string' || !/^[0-9a-fA-F]{128}$/.test(manifest.signature)) {
throw new Error('Invalid signature format')
}
if (typeof manifest.sequence !== 'number') throw new Error('Invalid sequence')
if (typeof manifest.timestamp !== 'number') throw new Error('Invalid timestamp')
if (!Array.isArray(manifest.collections)) throw new Error('Invalid collections')
// Reconstruct the payload to verify (exclude signature)
const payload = {
publicKey: manifest.publicKey,
sequence: manifest.sequence,
timestamp: manifest.timestamp,
collections: manifest.collections
}
const jsonString = stringify(payload)
const publicKey = Buffer.from(manifest.publicKey, 'hex')
const signature = Buffer.from(manifest.signature, 'hex')
if (typeof manifest.publicKey !== 'string') {
throw new Error('Invalid public key format')
}
if (typeof manifest.signature !== 'string') {
throw new Error('Invalid signature format')
}
// Normalize hex strings to lowercase for consistent handling
const publicKeyHex = manifest.publicKey.toLowerCase()
const signatureHex = manifest.signature.toLowerCase()
if (!/^[0-9a-f]{64}$/.test(publicKeyHex)) {
throw new Error('Invalid public key format')
}
if (!/^[0-9a-f]{128}$/.test(signatureHex)) {
throw new Error('Invalid signature format')
}
if (typeof manifest.sequence !== 'number') throw new Error('Invalid sequence')
if (typeof manifest.timestamp !== 'number') throw new Error('Invalid timestamp')
if (!Array.isArray(manifest.collections)) throw new Error('Invalid collections')
// Reconstruct the payload to verify (exclude signature)
const payload = {
publicKey: publicKeyHex,
sequence: manifest.sequence,
timestamp: manifest.timestamp,
collections: manifest.collections
}
const jsonString = stringify(payload)
const publicKey = Buffer.from(publicKeyHex, 'hex')
const signature = Buffer.from(signatureHex, 'hex')

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants