1
0

testFusion.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /* Import core modules. */
  2. const debug = require('debug')('cashfusion:test')
  3. const net = require('net')
  4. const numeral = require('numeral')
  5. const path = require('path')
  6. const protobuf = require('protobufjs')
  7. const GENESIS = '6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000'
  8. const HOST = 'cashfusion.electroncash.dk'
  9. const PORT = 8787
  10. const VERSION = 'alpha13'
  11. /* Initialize magic (bytes). */
  12. const magic = Buffer.from('765be8b4e4396dcf', 'hex')
  13. /* Initialize protobuf classes. */
  14. // const pbEnums = ['Phase', 'Reason']
  15. /* Initialize protobuf types. */
  16. const pbTypes = [
  17. 'InputComponent', 'OutputComponent', 'BlankComponent', 'Component',
  18. 'InitialCommitment', 'Proof', 'ClientHello', 'ServerHello', 'JoinPools',
  19. 'TierStatusUpdate', 'FusionBegin', 'StartRound', 'PlayerCommit',
  20. 'BlindSigResponses', 'AllCommitments', 'CovertComponent',
  21. 'ShareCovertComponents', 'CovertTransactionSignature', 'FusionResult',
  22. 'MyProofsList', 'TheirProofsList', 'Blames', 'RestartRound', 'Error',
  23. 'Ping', 'OK', 'ClientMessage', 'ServerMessage', 'CovertMessage',
  24. 'CovertResponse'
  25. ]
  26. /* Initialize tiers output. */
  27. let tiersOutput = null
  28. /**
  29. * Parse Players
  30. */
  31. const _parsePlayers = (_tier) => {
  32. if (_tier.timeRemaining) {
  33. /* Set time remaining. */
  34. const remaining = (_tier.timeRemaining / 60).toFixed(1) + ' mins remaining'
  35. return `${_tier.players} of ${_tier.minPlayers} [ ${remaining} ]`
  36. } else {
  37. return `${_tier.players} of ${_tier.minPlayers}`
  38. }
  39. }
  40. /* Initialize protobuf. */
  41. const PB = {
  42. root: protobuf.loadSync(path.join(__dirname, 'libs', 'fusion', 'fusion.proto'))
  43. }
  44. /* Loop through ALL protobuf types. */
  45. for (let oneTypeName of pbTypes) {
  46. PB[oneTypeName] = PB.root.lookupType(oneTypeName)
  47. }
  48. // debug('Protocol buffer', PB)
  49. /**
  50. * Greeting
  51. */
  52. const greet = function () {
  53. console.info('\n\tGreeting CashFusion server...\n') // eslint-disable-line no-console
  54. /* Set message. */
  55. const message = PB.ClientMessage.create({
  56. clienthello: PB.ClientHello.create({
  57. version: Buffer.from(VERSION),
  58. genesisHash: Buffer.from(GENESIS, 'hex')
  59. })
  60. })
  61. /* Verify message. */
  62. const errMsg = PB.ClientMessage.verify(message)
  63. if (errMsg) {
  64. // debug('Protobuf verification failed!', errMsg)
  65. throw new Error(errMsg)
  66. }
  67. /* Encode message. */
  68. const buffer = PB.ClientMessage.encode(message).finish()
  69. // debug('Encoded message:', buffer.toString('hex'))
  70. // const decoded = PB.ClientMessage.decode(buffer)
  71. // debug('Decoded:', decoded)
  72. /* Return packed message. */
  73. return packMessage(buffer)
  74. }
  75. /**
  76. * Register
  77. */
  78. const register = function () {
  79. console.info('\n\tRegistering tiers...\n') // eslint-disable-line no-console
  80. // All tiers
  81. // tiersOutput = [
  82. // 10000, 12000, 15000, 18000, 22000, 27000, 33000, 39000, 47000, 56000, 68000, 82000,
  83. // ]
  84. tiersOutput = [
  85. 10000, 12000, 15000, 18000, 22000, 27000, 33000, 39000, 47000, 56000, 68000, 82000,
  86. 100000, 120000, 150000, 180000, 220000, 270000, 330000, 390000, 470000, 560000, 680000, 820000,
  87. 1000000, 1200000, 1500000, 1800000, 2200000, 2700000, 3300000, 3900000, 4700000, 5600000, 6800000, 8200000,
  88. 10000000, 12000000, 15000000, 18000000, 22000000, 27000000, 33000000, 39000000, 47000000, 56000000, 68000000, 82000000
  89. ]
  90. debug('Tiers output:', tiersOutput.length, tiersOutput)
  91. /* Set message. */
  92. const message = PB.ClientMessage.create({
  93. joinpools: PB.JoinPools.create({
  94. tiers: tiersOutput,
  95. tags: [PB.JoinPools.PoolTag.create({
  96. // FIXME: Figure out what this id/tag means??
  97. id: Buffer.from('c58594f6f26f0315f459f06d4106084ae53058e3', 'hex'),
  98. limit: 1
  99. })]
  100. })
  101. })
  102. /* Verify message. */
  103. const errMsg = PB.ClientMessage.verify(message)
  104. if (errMsg) {
  105. // debug('Protobuf verification failed!', errMsg)
  106. throw new Error(errMsg)
  107. }
  108. /* Encode message. */
  109. const buffer = PB.ClientMessage.encode(message).finish()
  110. // debug('Encoded message:', buffer.toString('hex'))
  111. // const decoded = PB.ClientMessage.decode(buffer)
  112. // debug('Decoded:', decoded)
  113. /* Return packed message. */
  114. return packMessage(buffer)
  115. }
  116. /**
  117. * Pack Message
  118. *
  119. * Encode (pack) a message into a prototype buffer (protobuf) object.
  120. */
  121. function packMessage (_packets) {
  122. // debug('Packing message:', _packets)
  123. /* Initialize message length. */
  124. const messageLength = Buffer.allocUnsafe(4)
  125. /* Calculate message length. */
  126. const lengthDec = _packets.length
  127. /* Set message length. */
  128. // NOTE: 4-bytes in big-endian (bytes order).
  129. messageLength.writeUIntBE(lengthDec, 0, 4)
  130. // debug('Message length:', messageLength)
  131. /* Build packet. */
  132. const packet = Buffer.concat([
  133. magic,
  134. messageLength,
  135. _packets
  136. ])
  137. // debug('Packet message:', packet)
  138. return packet
  139. // _packets = _.isArray(_packets) ? _packets : [_packets]
  140. // const messageBuffer = _packets
  141. /* Initialize length suffix. */
  142. // const lengthSuffix = Buffer.alloc(4)
  143. /* Set length suffix. */
  144. // lengthSuffix.writeUIntBE(messageBuffer.length, 0, 4)
  145. /* Set message components. */
  146. // const messageComponents = [magic, lengthSuffix, messageBuffer]
  147. /* Set full message. */
  148. // const fullMessage = Buffer.concat(messageComponents)
  149. /* Return message object. */
  150. // return {
  151. // unpacked: _packets,
  152. // packed: fullMessage,
  153. // components: messageToBuffers(fullMessage)
  154. // }
  155. }
  156. /* Initialize client. */
  157. const client = new net.Socket()
  158. /**
  159. * Connect
  160. *
  161. * Opens a new connection to the host.
  162. */
  163. client.connect(PORT, HOST, function () {
  164. debug('Connected! (host/port):', HOST, PORT)
  165. /* Initialize greeting. */
  166. const greeting = greet()
  167. debug('Greeting', greeting.toString('hex'))
  168. /* Send greeting. */
  169. client.write(greeting)
  170. })
  171. /**
  172. * Handle Data
  173. *
  174. * Processes all data received from the host.
  175. */
  176. client.on('data', function (_data) {
  177. // debug('RECEIVED DATA:', _data)
  178. debug('Incoming data (from server):', Buffer.from(_data).toString('hex'))
  179. const message = _data.slice(magic.length + 4)
  180. // debug('Incoming data (message):', message.toString('hex'))
  181. const decoded = PB.ServerMessage.decode(message)
  182. debug('Incoming data (decoded):', decoded)
  183. /* Handle message. */
  184. if (decoded.serverhello) {
  185. /* Validate data. */
  186. if (!PB.ServerHello.verify(decoded.serverhello)) {
  187. debug('ServerHello (tiers):', decoded.serverhello.tiers)
  188. debug('ServerHello (numComponents):', decoded.serverhello.numComponents)
  189. debug('ServerHello (componentFeerate):', decoded.serverhello.componentFeerate)
  190. debug('ServerHello (minExcessFee):', decoded.serverhello.minExcessFee)
  191. debug('ServerHello (maxExcessFee):', decoded.serverhello.maxExcessFee)
  192. debug('ServerHello (donationAddress):', decoded.serverhello.donationAddress)
  193. /* Initialize registration. */
  194. const registration = register()
  195. debug('Registration', registration.toString('hex'))
  196. /* Send greeting. */
  197. client.write(registration)
  198. } else {
  199. throw new Error(PB.ServerHello.verify(decoded.serverhello))
  200. }
  201. }
  202. /* Handle data. */
  203. if (decoded.tierstatusupdate) {
  204. // console.log('DEBUG:', decoded.tierstatusupdate)
  205. const statuses = decoded.tierstatusupdate.statuses
  206. // debug('Tier statuses::', statuses)
  207. const keys = Object.keys(statuses)
  208. // debug('Tier keys:', decodeURIComponent(keys))
  209. /* Display each key status. */
  210. keys.forEach((key, i) => {
  211. // debug(i, decodeURIComponent(key), statuses[key])
  212. debug(`Tier ${numeral(tiersOutput[i]).format('0,0')} - ${_parsePlayers(statuses[key])}`)
  213. })
  214. client.destroy()
  215. // if (!PB.TierStatusUpdate.verify(decoded.tierstatusupdate)) {
  216. // debug('TierStatusUpdate (statuses):', decoded.tierstatusupdate.statuses)
  217. // } else if (decoded.tierstatusupdate) {
  218. // throw new Error(PB.TierStatusUpdate.verify(decoded.tierstatusupdate))
  219. // }
  220. }
  221. // Close the client socket completely
  222. // client.destroy()
  223. })
  224. /**
  225. * Handle Close
  226. *
  227. * Handles connection termination.
  228. */
  229. client.on('close', function () {
  230. debug('Connection closed.')
  231. })