Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save RahulMishra0722/5b388477ee8a6c85e23a36f86dcb7475 to your computer and use it in GitHub Desktop.
Save RahulMishra0722/5b388477ee8a6c85e23a36f86dcb7475 to your computer and use it in GitHub Desktop.
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