123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- /* Import core modules. */
- const debug = require('debug')('cashfusion:test')
- const net = require('net')
- const numeral = require('numeral')
- const path = require('path')
- const protobuf = require('protobufjs')
- const GENESIS = '6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000'
- const HOST = 'cashfusion.electroncash.dk'
- const PORT = 8787
- const VERSION = 'alpha13'
- /* Initialize magic (bytes). */
- const magic = Buffer.from('765be8b4e4396dcf', 'hex')
- /* Initialize protobuf classes. */
- // const pbEnums = ['Phase', 'Reason']
- /* Initialize protobuf types. */
- const pbTypes = [
- 'InputComponent', 'OutputComponent', 'BlankComponent', 'Component',
- 'InitialCommitment', 'Proof', 'ClientHello', 'ServerHello', 'JoinPools',
- 'TierStatusUpdate', 'FusionBegin', 'StartRound', 'PlayerCommit',
- 'BlindSigResponses', 'AllCommitments', 'CovertComponent',
- 'ShareCovertComponents', 'CovertTransactionSignature', 'FusionResult',
- 'MyProofsList', 'TheirProofsList', 'Blames', 'RestartRound', 'Error',
- 'Ping', 'OK', 'ClientMessage', 'ServerMessage', 'CovertMessage',
- 'CovertResponse'
- ]
- /* Initialize tiers output. */
- let tiersOutput = null
- /**
- * Parse Players
- */
- const _parsePlayers = (_tier) => {
- if (_tier.timeRemaining) {
- /* Set time remaining. */
- const remaining = (_tier.timeRemaining / 60).toFixed(1) + ' mins remaining'
- return `${_tier.players} of ${_tier.minPlayers} [ ${remaining} ]`
- } else {
- return `${_tier.players} of ${_tier.minPlayers}`
- }
- }
- /* Initialize protobuf. */
- const PB = {
- root: protobuf.loadSync(path.join(__dirname, 'libs', 'fusion', 'fusion.proto'))
- }
- /* Loop through ALL protobuf types. */
- for (let oneTypeName of pbTypes) {
- PB[oneTypeName] = PB.root.lookupType(oneTypeName)
- }
- // debug('Protocol buffer', PB)
- /**
- * Greeting
- */
- const greet = function () {
- console.info('\n\tGreeting CashFusion server...\n') // eslint-disable-line no-console
- /* Set message. */
- const message = PB.ClientMessage.create({
- clienthello: PB.ClientHello.create({
- version: Buffer.from(VERSION),
- genesisHash: Buffer.from(GENESIS, 'hex')
- })
- })
- /* Verify message. */
- const errMsg = PB.ClientMessage.verify(message)
- if (errMsg) {
- // debug('Protobuf verification failed!', errMsg)
- throw new Error(errMsg)
- }
- /* Encode message. */
- const buffer = PB.ClientMessage.encode(message).finish()
- // debug('Encoded message:', buffer.toString('hex'))
- // const decoded = PB.ClientMessage.decode(buffer)
- // debug('Decoded:', decoded)
- /* Return packed message. */
- return packMessage(buffer)
- }
- /**
- * Register
- */
- const register = function () {
- console.info('\n\tRegistering tiers...\n') // eslint-disable-line no-console
- // All tiers
- // tiersOutput = [
- // 10000, 12000, 15000, 18000, 22000, 27000, 33000, 39000, 47000, 56000, 68000, 82000,
- // ]
- tiersOutput = [
- 10000, 12000, 15000, 18000, 22000, 27000, 33000, 39000, 47000, 56000, 68000, 82000,
- 100000, 120000, 150000, 180000, 220000, 270000, 330000, 390000, 470000, 560000, 680000, 820000,
- 1000000, 1200000, 1500000, 1800000, 2200000, 2700000, 3300000, 3900000, 4700000, 5600000, 6800000, 8200000,
- 10000000, 12000000, 15000000, 18000000, 22000000, 27000000, 33000000, 39000000, 47000000, 56000000, 68000000, 82000000
- ]
- debug('Tiers output:', tiersOutput.length, tiersOutput)
- /* Set message. */
- const message = PB.ClientMessage.create({
- joinpools: PB.JoinPools.create({
- tiers: tiersOutput,
- tags: [PB.JoinPools.PoolTag.create({
- // FIXME: Figure out what this id/tag means??
- id: Buffer.from('c58594f6f26f0315f459f06d4106084ae53058e3', 'hex'),
- limit: 1
- })]
- })
- })
- /* Verify message. */
- const errMsg = PB.ClientMessage.verify(message)
- if (errMsg) {
- // debug('Protobuf verification failed!', errMsg)
- throw new Error(errMsg)
- }
- /* Encode message. */
- const buffer = PB.ClientMessage.encode(message).finish()
- // debug('Encoded message:', buffer.toString('hex'))
- // const decoded = PB.ClientMessage.decode(buffer)
- // debug('Decoded:', decoded)
- /* Return packed message. */
- return packMessage(buffer)
- }
- /**
- * Pack Message
- *
- * Encode (pack) a message into a prototype buffer (protobuf) object.
- */
- function packMessage (_packets) {
- // debug('Packing message:', _packets)
- /* Initialize message length. */
- const messageLength = Buffer.allocUnsafe(4)
- /* Calculate message length. */
- const lengthDec = _packets.length
- /* Set message length. */
- // NOTE: 4-bytes in big-endian (bytes order).
- messageLength.writeUIntBE(lengthDec, 0, 4)
- // debug('Message length:', messageLength)
- /* Build packet. */
- const packet = Buffer.concat([
- magic,
- messageLength,
- _packets
- ])
- // debug('Packet message:', packet)
- return packet
- // _packets = _.isArray(_packets) ? _packets : [_packets]
- // const messageBuffer = _packets
- /* Initialize length suffix. */
- // const lengthSuffix = Buffer.alloc(4)
- /* Set length suffix. */
- // lengthSuffix.writeUIntBE(messageBuffer.length, 0, 4)
- /* Set message components. */
- // const messageComponents = [magic, lengthSuffix, messageBuffer]
- /* Set full message. */
- // const fullMessage = Buffer.concat(messageComponents)
- /* Return message object. */
- // return {
- // unpacked: _packets,
- // packed: fullMessage,
- // components: messageToBuffers(fullMessage)
- // }
- }
- /* Initialize client. */
- const client = new net.Socket()
- /**
- * Connect
- *
- * Opens a new connection to the host.
- */
- client.connect(PORT, HOST, function () {
- debug('Connected! (host/port):', HOST, PORT)
- /* Initialize greeting. */
- const greeting = greet()
- debug('Greeting', greeting.toString('hex'))
- /* Send greeting. */
- client.write(greeting)
- })
- /**
- * Handle Data
- *
- * Processes all data received from the host.
- */
- client.on('data', function (_data) {
- // debug('RECEIVED DATA:', _data)
- debug('Incoming data (from server):', Buffer.from(_data).toString('hex'))
- const message = _data.slice(magic.length + 4)
- // debug('Incoming data (message):', message.toString('hex'))
- const decoded = PB.ServerMessage.decode(message)
- debug('Incoming data (decoded):', decoded)
- /* Handle message. */
- if (decoded.serverhello) {
- /* Validate data. */
- if (!PB.ServerHello.verify(decoded.serverhello)) {
- debug('ServerHello (tiers):', decoded.serverhello.tiers)
- debug('ServerHello (numComponents):', decoded.serverhello.numComponents)
- debug('ServerHello (componentFeerate):', decoded.serverhello.componentFeerate)
- debug('ServerHello (minExcessFee):', decoded.serverhello.minExcessFee)
- debug('ServerHello (maxExcessFee):', decoded.serverhello.maxExcessFee)
- debug('ServerHello (donationAddress):', decoded.serverhello.donationAddress)
- /* Initialize registration. */
- const registration = register()
- debug('Registration', registration.toString('hex'))
- /* Send greeting. */
- client.write(registration)
- } else {
- throw new Error(PB.ServerHello.verify(decoded.serverhello))
- }
- }
- /* Handle data. */
- if (decoded.tierstatusupdate) {
- // console.log('DEBUG:', decoded.tierstatusupdate)
- const statuses = decoded.tierstatusupdate.statuses
- // debug('Tier statuses::', statuses)
- const keys = Object.keys(statuses)
- // debug('Tier keys:', decodeURIComponent(keys))
- /* Display each key status. */
- keys.forEach((key, i) => {
- // debug(i, decodeURIComponent(key), statuses[key])
- debug(`Tier ${numeral(tiersOutput[i]).format('0,0')} - ${_parsePlayers(statuses[key])}`)
- })
- client.destroy()
- // if (!PB.TierStatusUpdate.verify(decoded.tierstatusupdate)) {
- // debug('TierStatusUpdate (statuses):', decoded.tierstatusupdate.statuses)
- // } else if (decoded.tierstatusupdate) {
- // throw new Error(PB.TierStatusUpdate.verify(decoded.tierstatusupdate))
- // }
- }
- // Close the client socket completely
- // client.destroy()
- })
- /**
- * Handle Close
- *
- * Handles connection termination.
- */
- client.on('close', function () {
- debug('Connection closed.')
- })
|