Created
August 22, 2024 15:09
-
-
Save RahulMishra0722/5b388477ee8a6c85e23a36f86dcb7475 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import WebSocket, { WebSocketServer } from 'ws'; | |
import crypto from 'crypto'; | |
export class Node { | |
private isValidTransactionFlag: boolean; | |
private data: string; | |
private wsServer: WebSocketServer; | |
private wsClients: WebSocket[]; | |
constructor() { | |
this.isValidTransactionFlag = false; | |
this.data = 'something'; | |
this.wsClients = []; | |
this.wsServer = new WebSocketServer({ port: 7777 }); | |
this.wsServer.on('connection', (ws: WebSocket) => { | |
console.log('New client connected'); | |
this.wsClients.push(ws); | |
ws.on('message', (message: WebSocket.MessageEvent) => { | |
console.log('Received message:', message); | |
this.handleMessage(message); | |
}); | |
ws.on('close', () => { | |
console.log('Client disconnected'); | |
this.wsClients = this.wsClients.filter(client => client !== ws); | |
}); | |
}); | |
this.listenForBlockCreation(); | |
} | |
private handleMessage(message: WebSocket.MessageEvent): void { | |
try { | |
const transaction = JSON.parse(message.toString()); | |
console.log('Parsed message data:', transaction); | |
if (transaction.fee && transaction.sender && transaction.receiver) { | |
console.log('Received transaction:', transaction); | |
this.validateTransaction(transaction); | |
} else { | |
console.warn('Unknown message format:', transaction); | |
} | |
} catch (error) { | |
console.error('Error handling message:', error); | |
} | |
} | |
verify_signature(publicKey: string, data: any, signature: string): boolean { | |
try { | |
const isVerified = crypto.verify( | |
"sha256", | |
Buffer.from(data), | |
{ | |
key: publicKey, | |
padding: crypto.constants.RSA_PKCS1_PSS_PADDING, | |
}, | |
Buffer.from(signature, 'hex') | |
) | |
return isVerified; | |
} catch (error) { | |
console.error('Error verifying signature:', error); | |
return false; | |
} | |
} | |
sign_signature(data: any): string | undefined { | |
try { | |
const convertKeyToBuffer = (key: string): Buffer => { | |
return Buffer.from(key, 'base64'); | |
}; | |
const transaction_data = `${data.sender}${data.receiver}${data.amount}${data.fee}`; | |
const privateKeyBuffer = convertKeyToBuffer(data.privateKey); | |
const privateKey = `-----BEGIN PRIVATE KEY-----\n${privateKeyBuffer.toString('base64').match(/.{1,64}/g)?.join('\n')}\n-----END PRIVATE KEY-----\n`; | |
const signature = crypto.sign( | |
'sha256', | |
Buffer.from(transaction_data), | |
{ | |
key: privateKey, | |
padding: crypto.constants.RSA_PKCS1_PSS_PADDING, | |
} | |
); | |
return signature.toString('hex'); | |
} catch (error) { | |
console.error('Error signing transaction:', error); | |
return undefined; | |
} | |
} | |
validate_proof_of_work(block: any): boolean { | |
return true; | |
} | |
sendTxnToMempool(data: string): void { | |
this.broadcast({ type: 'txn', data }); | |
} | |
compute_merkleRoot(transactions: any[]): string { | |
return 'computed_merkle_root'; | |
} | |
compute_blockHash(block: any): string { | |
return 'computed_block_hash'; | |
} | |
convertKeyToBuffer(key: string): Buffer { | |
return Buffer.from(key, 'base64'); | |
}; | |
async validateTransaction(data: any): Promise<void> { | |
const signature = this.sign_signature(data); | |
if (signature) { | |
const publicKeyBuffer = this.convertKeyToBuffer(data.sender); | |
const formattedPublicKey = `-----BEGIN PUBLIC KEY-----\n${publicKeyBuffer.toString('base64').match(/.{1,64}/g)?.join('\n')}\n-----END PUBLIC KEY-----\n`; | |
const transaction_data = `${data.sender}${data.receiver}${data.amount}${data.fee}` | |
const isSignatureValid = this.verify_signature(formattedPublicKey, transaction_data, signature); | |
} else { | |
console.error('Signature not obtained'); | |
} | |
} | |
get isValidTransaction(): boolean { | |
return this.isValidTransactionFlag; | |
} | |
private listenForBlockCreation(): void { | |
this.wsServer.on('message', (message: WebSocket.MessageEvent) => { | |
const data = JSON.parse(message.data.toString()); | |
if (data.type === 'blockCreated') { | |
this.handleNewBlock(data.block); | |
} | |
}); | |
} | |
private handleNewBlock(block: any): void { | |
console.log('Handling new block:', block); | |
const isProofOfWorkValid = this.validate_proof_of_work(block); | |
if (!isProofOfWorkValid) { | |
console.error('Invalid Proof of Work'); | |
return; // Reject the block | |
} | |
// Validate the block's transactions (Merkle Root) | |
const computedMerkleRoot = this.compute_merkleRoot(block.transactions); | |
if (computedMerkleRoot !== block.merkleRoot) { | |
console.error('Invalid Merkle Root:', computedMerkleRoot); | |
return; // Reject the block | |
} | |
// Validate the block's hash | |
const computedBlockHash = this.compute_blockHash(block); | |
if (computedBlockHash !== block.blockHash) { | |
console.error('Invalid Block Hash:', computedBlockHash); | |
return; // Reject the block | |
} | |
this.broadcastBlock(block); | |
} | |
// Broadcasts the block to the network | |
private broadcastBlock(block: any): void { | |
console.log('Broadcasting block to network:', block); | |
this.broadcast({ type: 'blockCreated', block }); | |
} | |
// Helper method to broadcast data to all connected WebSocket clients | |
private broadcast(message: any): void { | |
const data = JSON.stringify(message); | |
this.wsClients.forEach(client => { | |
if (client.readyState === WebSocket.OPEN) { | |
client.send(data); | |
} | |
}); | |
} | |
} | |
const node = new Node(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment