Cómo programar tu propio minero de bitcoins, y no morir en el intento
Posted by Albert Zotkin on March 23, 2021
server-pool.js
const Net = require('net'); const url = require('url'); const bitcore = require('bitcore-lib'); const Hash = bitcore.crypto.Hash; const BufferUtil = bitcore.util.buffer; const _ = require('./util'); const prettify = require('../prettify.js')(); const stdin = process.openStdin(); const fs = require('fs'); const users_file ='./user.json'; const DT = require('./datatypes'); const $ = require('./util'); const get = require('./manageGetRequest'); const MBP = require('./make-block-project'); var t_url = url.parse('http://127.0.0.1:3000/'); var port = t_url.port; /* const options = { key: fs.readFileSync('./openssl/key.pem'), cert: fs.readFileSync('./openssl/cert.pem') }; */ const server = new Net.Server(); var chats = []; var current_chat = null; var current_block_project = null; var ids = 0; var users = JSON.parse(fs.readFileSync(users_file, function(err){ if(err) throw(err); })); const MAX_HISTORY_SIZE = 40; const QUORUM_PERCENT = 74; // //percentage of minimum number of miners to proceed mining var jobready_count = 0; server.listen(port, function() { console.log('\x1b[36m\x1b[2m[Server listening for connection requests on socket\x1b[0m:'); //console.log(users); }); stdin.addListener("data", function(d) { /* var sentence = d.toString().trim(); talkTo(sentence); sanitizeChats(); */ var sentence = d.toString().trim(); var line = sentence.split('>'); var header = line[0]; var body =line[1]; switch (header){ case 'stop': broadcast2All(DT.StopMessage()); break; case 'new'://'new-block-project': MBP.startNewBlockProject(false); //true =>get actual data from blockchain.info break; case 'ping': if(current_chat) current_chat.socket.write(DT.PingMessage()); else console.error({error:'no clients connected'}); break; case 'broadcast': broadcast2All(DT.testMessage()); break; case 'exit': console.log("\x1b[33m[Server is about to be closed]\x1b[0m"); server.destroy(); setTimeout(function(){ process.exit(0)}, 1000); // kill client break; case 'exit': break; default: talkTo(sentence); sanitizeChats(); break; } }); server.on('connection', function(socket) { console.log('\x1b[36mA new connection has been established\x1b[0m.'); //current_chat = setChat(socket); //talkTo(); socket.on('data', function(chunk) { current_chat = setChat(socket); var msg = DT.readMessage(chunk); if(msg)talkFromMessage(msg); else { var sentence = chunk.toString().split('\n'); var w = chunk.toString().split(' '); var word = w[0]; switch(word){ case 'GET': /* current_chat.socket.write([ 'HTTP/1.1 200 OK', 'Content-Type: text/html; charset=UTF-8', 'Content-Encoding: UTF-8', 'Accept-Ranges: bytes', 'Connection: keep-alive', ].join('\n') + '\n\n'); current_chat.socket.write('<h1> Example </h1> <img src ="../uploads/building.jpg"> '); // console.log(sentence[0].split(' ')[1]); //current_chat.socket.end(); */ get.ManageGetRequest(chunk,socket) console.log(chunk.toString()); break; default: talkFrom(chunk.toString()); break; } } }); socket.on('end', function() { current_chat = setChat(socket); console.log('\x1b[36m\x1b[2mClosing connection with the client %s\x1b[0m.',current_chat.user); removeChat(socket); current_chat = null; }); socket.on('error', function(err) { current_chat = setChat(socket); console.log(err); }); }); function talkTo(message){ if(current_chat){ var msg = message; if(current_chat.user === 'anonymous' ){ msg = '\x1b[32mHello, \x1b[1mUSER:PWD\x1b[0m\x1b[32m, please\x1b[0m' } if(msg){ current_chat.socket.write(msg); current_chat.history.push(msg); } } } function talkFrom(message){ if(current_chat){ if(current_chat.user === 'anonymous'){ var msg = message.split(':'); if(msg.length == 2) checkUserPwd(msg,current_chat); talkTo(); } console.log('%s: \x1b[33m%s\x1b[0m',current_chat.user, message); current_chat.history.push(message); } } function talkFromMessage(m){ if(current_chat){ if(current_chat.user === 'anonymous'){ var msg = m.payload.toString('utf8').split(':'); if(msg.length == 2) checkUserPwd(msg,current_chat); talkTo(); } onCommand(m); var obj = {};obj[current_chat.user]= m; console.log(obj); current_chat.history.push(JSON.stringify(m)); } } /* function checkUserPwd(msg, chat){ for(var e in users){ if(msg[0] === e && msg[1] === users[e].pwd ){ for(var f in chats){ if(chats[f].socket == chat.socket){ chats[f].user = msg[0]; chat.socket.write('Thanks ' + chats[f].user); return true; } } } } return false; } */ function checkUserPwd(msg, chat){ for(var e in users){ if(msg[0] === e && msg[1] === users[e].pwd){ for(var f in chats){ if(chats[f].user == msg[0]) return false; if(chats[f].socket == chat.socket){ chats[f].user = msg[0]; chat.socket.write('Welcome ' + chats[f].user); return true; } } } } return false; } function sanitizeChats(){ for(var e in chats){ if(chats[e].history.length > MAX_HISTORY_SIZE) chats[e].history.shift(); } } function setChat(socket){ var chat = {user:'anonymous',id :-1,socket:socket,history:[]}; for(var e in chats){ if(chat.socket == chats[e].socket) return chats[e]; } chat.id =ids++; chats.push(chat); return chat; } function resumeChat(user, socket){ var chat = {user:user, id:-1, socket:socket, history:[]}; for(var e in chats){ if(user == chats[e].user){ chats[e].socket = socket; return chats[e]; } } chat.id =ids++; chats.push(chat); return chat; } function removeChat(socket){ for(var e in chats){ if(chats[e].socket == socket){ chats.splice(e, 1); } } } function broadcast2All(message){ if(chats)for(var e in chats){ chats[e].socket.write(message); } } function sendNoncePartition2All(){ var size = chats.length; var a = getNoncePartition(); var buf = new Buffer.alloc(8); if(chats)for(var e=0;e<size;e++){ buf.writeUInt32BE(a[e],0); buf.writeUInt32BE(a[e+1],4); var nonce_p ={ command: 'nonce_p', networkMagic: new Buffer.from('FF00FF00', 'hex'), payload: buf }; var msg = DT.makeMessage(nonce_p); /* var msg2 = DT.readMessage(msg); var p = [ msg2.payload.readUInt32BE(0), msg2.payload.readUInt32BE(4) ]; console.log(msg2); */ chats[e].socket.write(msg); } } function getNoncePartition(){ var size = chats.length; const nonce = 0xffffffff; var p = Math.floor(parseFloat(nonce)/size); var b = []; for(var i = 0;i<size;i++){ b.push(i*p); } b.push(nonce); return b; //return_.SplitInterval([0,45676543],6)); } function onCommand(msg){ var command = msg.command; switch(command){ case 'ping': current_chat.socket.write(DT.PongMessage(msg)); break; case 'joback': jobready_count++; if(jobready_count >= chats.length){ jobready_count=0; sendNoncePartition2All(); } break; case 'block_solved': try{ var file = 'solved-'+ Date.now()+'.hex'; fs.writeFileSync(file,msg.payload.toString('hex'),'utf8'); broadcast2All(DT.StopMessage()); }catch(e){ console.error(e); } break; /* case: break; case: break; case: break; */ } } MBP.emitter.on('new-block-project-ready', () => { console.log('\x1b[33mnew-\x1b[1mblock-project\x1b[0m\x1b[33m-ready:\x1b[0m'); current_block_project = new bitcore.Block.fromBuffer(MBP.get_block_project()); console.log(current_block_project.header.toObject()); broadcast2All(DT.JobMessage(current_block_project.header.toBuffer())); });
util.js
'use strict'; const bitcore = require('bitcore-lib'); const Random = bitcore.crypto.Random; var $ = bitcore.util.preconditions; const BufferReader = bitcore.encoding.BufferReader; const BufferWriter = bitcore.encoding.BufferWriter; const OUTPUT = 1; const INPUT = 0; /* Can parse a JSON object even if there are comment tags between its items */ var parseW = function(str){ return JSON.parse(str.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1')); } function variantToBufferFromNum(n){ return new BufferWriter(new Buffer.alloc(0)) .writeVarintNum(n) .toBuffer(); } function SplitInterval(partition,n){ if(typeof partition !== 'object') return null; if(typeof partition[0] !== 'number' || typeof partition[1] !== 'number') return null; if( partition[1] - partition[0] <= 0) return null; var d = Math.floor((partition[1]-partition[0])/n); var b = []; for(var j = 0;j<n;j++){ var c = []; c.push(partition[0] + d*j); c.push(partition[0] + d*(j+1)-1); b.push(c); } b[n-1][1] = partition[1]; return b; } function format_date(timestamp){ var date = new Date(timestamp * 1000); var day = date.getDate(); //var month = months_arr[date.getMonth()]; var month = date.getMonth()+1; var year = date.getFullYear(); var hours = date.getHours(); var minutes = "0" + date.getMinutes(); var seconds = "0" + date.getSeconds(); // Will display time in 10:30:23 format var formattedTime = month + '/' + day + '/' +year + ' ' + hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2); return formattedTime; } /* split buffer buf into an array of subbuffers, separator must be a string of bytes in hexadecimal mode. */ function Split(buf, separator){ var occurr =[]; var sp =[]; var b = new Buffer.from(buf); var pos = 0; var i = 0; const magic = new Buffer.from(separator, 'hex'); while(1){ var index = b.indexOf(magic); if(index > -1){ pos += index; occurr.push(pos+magic.length*i);i++; b = b.slice(index+magic.length); }else break; } if(occurr.length){ if(occurr[0]>0) sp.push(buf.slice(0,occurr[0])); for(var i = 0;i<occurr.length;i++) sp.push(buf.slice(occurr[i],occurr[i+1])); /*if(occurr[occurr.length-1]< buf.length-1) sp.push(buf.slice(occurr[occurr.length-1]));*/ } else sp.push(buf); return sp; } Buffer['split'] = Split; //let Global Object, Buffer, manages this. JSON['parseW'] = parseW; //let Global Object, JSON, manages this. function WM_Encrypt(buffer, mode){ if(buffer.length){ var puntero = 0; var size = buffer.length; while(puntero < size/2) { Traspuesta(puntero,size-puntero-1,mode,buffer); puntero++; } } return buffer; } function Traspuesta(i, j, modo, buffer){ var nparam1,nparam2; nparam1 = buffer.readUInt8(i); if(modo)nparam1 = nparam1 - 10; else nparam1 = nparam1 + 10; nparam1 = nparam1<0?256+nparam1:nparam1; nparam1 = nparam1>0xff?nparam1-256:nparam1; nparam2 = buffer.readUInt8(j);//flujofichero.charCodeAt(j); if(modo)nparam2 = nparam2 - 10; else nparam2 = nparam2 + 10; nparam2 = nparam2<0?256+nparam2:nparam2; nparam2 = nparam2>0xff?nparam2-256:nparam2; buffer.writeUInt8(nparam2, i); buffer.writeUInt8(nparam1, j); } function wm_encode(buffer){ return WM_Encrypt(buffer, OUTPUT); } function wm_decode(buffer){ return WM_Encrypt(buffer, INPUT); } function stochash256(buffer){ if(buffer.length !== 256) return null; var pt =0; var hash = [] while(1){ var byte = buffer.readUInt8(pt); var repunit = getRepunit(byte); var rnd = Random.getRandomBuffer(1).readUInt8(0); hash.push(repunit[rnd]); pt++; if(pt == buffer.length)break; } var result = new bitcore.crypto.BN.fromString(hash.join(''),2); return result.toBuffer(); } function getRepunit(byte){ const two = new bitcore.crypto.BN(2); const one = new bitcore.crypto.BN(1); var b = new bitcore.crypto.BN(byte); var repunit = two.pow(b); repunit = repunit.sub(one); return repunit.toString(2,256); } module.exports = { SplitInterval:SplitInterval, variantToBufferFromNum:variantToBufferFromNum, format_date:format_date, WM_Encrypt:WM_Encrypt, wm_encode:wm_encode, wm_decode:wm_decode, stochash256:stochash256, getRepunit:getRepunit };
This entry was posted on March 23, 2021 at 2:21 pm and is filed under Bitcoin, criptografía, Criptomonedas, curiosidades y analogías, informática, Satoshi. Tagged: address, altura, altura de bloque, último bloque, bcperblock, Bitcoin, bitcoin network, bitcore, bitcore-lib, bits, block project, blockchain, blockchain.info, bloque, Bloque Génesis, broadcast, buffer, callback, chat, checksum, clave, claves, client, coinbase, command, compute, data, datatype, datatype.js, decode, difficulty, dificultad, dirección, dirección pública, doble hash, emisor, emitter, encode, encrypt, endian, endianness, ENTER, error, EventEmitter, evento, genesis block, hash, hashes, header, hexadecimal, history, http, https, javascript, job, JSON, json-colorizer, keys, keys.json, last block, librería, link, llave, llaves, localhost, magic, main, manage, método, Merkle root, merkleRoot, message, miner, miner-client.js, minería de bitcoin, minero, mining, namecoin, network, node.js, nodejs, nonce, npm, parser, payload, ping, plantilla, pong, pool, prettify.js, prevHash, proyecto de bloque, public address, query, remote, remoto, repunit, request, require, response, secure, server-poo, server-pool.js, socket, stohash, target, test, timestamp, toString, toUpperCase, transaction, unconfirmed transaction, url, user.json, use_strict, util.js, verack, verackmessage, version, wallernet, worker, worker_threads. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
Leave a comment