You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

464 lines
14KB

  1. var fs = require('fs');
  2. var stream = fs.createWriteStream("proglog.txt");
  3. var utils = require("./utils.js");
  4. var genesisCoinbaseTransactionTxid = "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b";
  5. var genesisCoinbaseTransaction = {
  6. "hex": "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d02fd04ffffffff0100f2052a01000000434104f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446aac00000000",
  7. "txid": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
  8. "hash": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
  9. "size": 204,
  10. "vsize": 204,
  11. "version": 1,
  12. "confirmations": 475000,
  13. "vin": [{
  14. "coinbase": "04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73",
  15. "sequence": 4294967295
  16. }],
  17. "vout": [{
  18. "value": 50,
  19. "n": 0,
  20. "scriptPubKey": {
  21. "asm": "04f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446a OP_CHECKSIG",
  22. "hex": "4104f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446aac",
  23. "reqSigs": 1,
  24. "type": "pubkey",
  25. "addresses": [
  26. "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
  27. ]
  28. }
  29. }],
  30. "blockhash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
  31. "time": 1230988505,
  32. "blocktime": 1230988505
  33. };
  34. function getInfo() {
  35. return new Promise(function(resolve, reject) {
  36. client.cmd('getinfo', function(err, result, resHeaders) {
  37. if (err) {
  38. console.log("Error 3207fh0f: " + err);
  39. reject(err);
  40. return;
  41. }
  42. resolve(result);
  43. });
  44. });
  45. }
  46. function getMiningInfo() {
  47. return new Promise(function(resolve, reject) {
  48. client.cmd('getmininginfo', function(err, result, resHeaders) {
  49. if (err) {
  50. console.log("Error 3207fh0f: " + err);
  51. reject(err);
  52. return;
  53. }
  54. resolve(result);
  55. });
  56. });
  57. }
  58. function getMempoolInfo() {
  59. return new Promise(function(resolve, reject) {
  60. client.cmd('getmempoolinfo', function(err, result, resHeaders) {
  61. if (err) {
  62. console.log("Error 23407rhwe07fg: " + err);
  63. reject(err);
  64. return;
  65. }
  66. resolve(result);
  67. });
  68. });
  69. }
  70. function getMempoolStats() {
  71. return new Promise(function(resolve, reject) {
  72. client.cmd('getrawmempool', true, function(err, result, resHeaders) {
  73. if (err) {
  74. console.log("Error 428thwre0ufg: " + err);
  75. reject(err);
  76. return;
  77. }
  78. var compiledResult = {};
  79. compiledResult.count = 0;
  80. compiledResult.fee_0_5 = 0;
  81. compiledResult.fee_6_10 = 0;
  82. compiledResult.fee_11_25 = 0;
  83. compiledResult.fee_26_50 = 0;
  84. compiledResult.fee_51_75 = 0;
  85. compiledResult.fee_76_100 = 0;
  86. compiledResult.fee_101_150 = 0;
  87. compiledResult.fee_151_max = 0;
  88. var totalFee = 0;
  89. for (var txid in result) {
  90. var txMempoolInfo = result[txid];
  91. totalFee += txMempoolInfo.modifiedfee;
  92. var feeRate = Math.round(txMempoolInfo.modifiedfee * 100000000 / txMempoolInfo.size);
  93. if (feeRate <= 5) {
  94. compiledResult.fee_0_5++;
  95. } else if (feeRate <= 10) {
  96. compiledResult.fee_6_10++;
  97. } else if (feeRate <= 25) {
  98. compiledResult.fee_11_25++;
  99. } else if (feeRate <= 50) {
  100. compiledResult.fee_26_50++;
  101. } else if (feeRate <= 75) {
  102. compiledResult.fee_51_75++;
  103. } else if (feeRate <= 100) {
  104. compiledResult.fee_76_100++;
  105. } else if (feeRate <= 150) {
  106. compiledResult.fee_101_150++;
  107. } else {
  108. compiledResult.fee_151_max++;
  109. }
  110. compiledResult.count++;
  111. }
  112. compiledResult.totalFee = totalFee;
  113. resolve(compiledResult);
  114. });
  115. });
  116. }
  117. function getBlockByHeight(blockHeight) {
  118. console.log("getBlockByHeightzz: " + blockHeight);
  119. console.log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxx \n");
  120. //*************************************************************************************
  121. stream.write('block:' + blockHeight);
  122. return new Promise(function(resolve, reject) {
  123. var client = global.client;
  124. client.cmd('getblockhash', blockHeight, function(err, result, resHeaders) {
  125. if (err) {
  126. console.log("Error 0928317yr3w: " + err);
  127. reject(err);
  128. return;
  129. }
  130. client.cmd('getblock', result, function(err2, result2, resHeaders2) {
  131. if (err2) {
  132. console.log("Error 320fh7e0hg: " + err2);
  133. reject(err2);
  134. return;
  135. }
  136. resolve({ success: true, getblockhash: result, getblock: result2 });
  137. });
  138. });
  139. });
  140. }
  141. function getBlocksByHeight(blockHeights) {
  142. console.log("getBlocksByHeight: " + blockHeights);
  143. console.log("getBlockByHeightzz: " + blockHeights);
  144. console.log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxx \n");
  145. //*************************************************************************************
  146. stream.write('block:' + blockHeights + "\n");
  147. return new Promise(function(resolve, reject) {
  148. var batch = [];
  149. for (var i = 0; i < blockHeights.length; i++) {
  150. batch.push({
  151. method: 'getblockhash',
  152. params: [blockHeights[i]]
  153. });
  154. }
  155. var blockHashes = [];
  156. client.cmd(batch, function(err, result, resHeaders) {
  157. blockHashes.push(result);
  158. if (blockHashes.length == batch.length) {
  159. var batch2 = [];
  160. for (var i = 0; i < blockHashes.length; i++) {
  161. batch2.push({
  162. method: 'getblock',
  163. params: [blockHashes[i]]
  164. });
  165. }
  166. var blocks = [];
  167. client.cmd(batch2, function(err2, result2, resHeaders2) {
  168. if (err2) {
  169. console.log("Error 138ryweufdf: " + err2);
  170. }
  171. blocks.push(result2);
  172. if (blocks.length == batch2.length) {
  173. resolve(blocks);
  174. }
  175. });
  176. }
  177. });
  178. });
  179. }
  180. function getBlockByHash(blockHash) {
  181. console.log("getBlockByHash: " + blockHash);
  182. return new Promise(function(resolve, reject) {
  183. var client = global.client;
  184. client.cmd('getblock', blockHash, function(err, result, resHeaders) {
  185. if (err) {
  186. console.log("Error 0u2fgewue: " + err);
  187. reject(err);
  188. return;
  189. }
  190. resolve(result);
  191. });
  192. });
  193. }
  194. function getTransactionInputs(rpcClient, transaction, inputLimit = 0) {
  195. console.log("getTransactionInputs: " + transaction.txid);
  196. return new Promise(function(resolve, reject) {
  197. var txids = [];
  198. for (var i = 0; i < transaction.vin.length; i++) {
  199. if (i < inputLimit || inputLimit == 0) {
  200. txids.push(transaction.vin[i].txid);
  201. }
  202. }
  203. getRawTransactions(txids).then(function(inputTransactions) {
  204. resolve({ txid: transaction.txid, inputTransactions: inputTransactions });
  205. });
  206. });
  207. }
  208. function getRawTransaction(txid) {
  209. return new Promise(function(resolve, reject) {
  210. if (txid == genesisCoinbaseTransactionTxid) {
  211. getBlockByHeight(0).then(function(blockZeroResult) {
  212. var result = genesisCoinbaseTransaction;
  213. result.confirmations = blockZeroResult.getblock.confirmations;
  214. resolve(result);
  215. });
  216. return;
  217. }
  218. client.cmd('getrawtransaction', txid, 1, function(err, result, resHeaders) {
  219. if (err) {
  220. console.log("Error 329813yre823: " + err);
  221. reject(err);
  222. return;
  223. }
  224. resolve(result);
  225. });
  226. });
  227. }
  228. function getRawTransactions(txids) {
  229. console.log("getRawTransactions: " + txids);
  230. return new Promise(function(resolve, reject) {
  231. if (!txids || txids.length == 0) {
  232. resolve([]);
  233. return;
  234. }
  235. if (txids.length == 1 && txids[0] == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b") {
  236. // copy the "confirmations" field from genesis block to the genesis-coinbase tx
  237. getBlockByHeight(0).then(function(blockZeroResult) {
  238. var result = genesisCoinbaseTransaction;
  239. result.confirmations = blockZeroResult.getblock.confirmations;
  240. resolve([result]);
  241. }).catch(function(err) {
  242. reject(err);
  243. return;
  244. });
  245. return;
  246. }
  247. var requests = [];
  248. for (var i = 0; i < txids.length; i++) {
  249. var txid = txids[i];
  250. if (txid) {
  251. requests.push({
  252. method: 'getrawtransaction',
  253. params: [txid, 1]
  254. });
  255. }
  256. }
  257. var requestBatches = utils.splitArrayIntoChunks(requests, 20);
  258. executeBatchesSequentially(requestBatches, function(results) {
  259. resolve(results);
  260. });
  261. });
  262. }
  263. function executeBatchesSequentially(batches, resultFunc) {
  264. var batchId = utils.getRandomString(20, 'aA#');
  265. console.log("Starting " + batches.length + "-item batch " + batchId + "...");
  266. executeBatchesSequentiallyInternal(batchId, batches, 0, [], resultFunc);
  267. }
  268. function executeBatchesSequentiallyInternal(batchId, batches, currentIndex, accumulatedResults, resultFunc) {
  269. if (currentIndex == batches.length) {
  270. console.log("Finishing batch " + batchId + "...");
  271. resultFunc(accumulatedResults);
  272. return;
  273. }
  274. console.log("Executing item #" + (currentIndex + 1) + " (of " + batches.length + ") for batch " + batchId);
  275. var count = batches[currentIndex].length;
  276. client.cmd(batches[currentIndex], function(err, result, resHeaders) {
  277. if (err) {
  278. console.log("Error f83024hf4: " + err);
  279. }
  280. accumulatedResults.push(result);
  281. count--;
  282. if (count == 0) {
  283. executeBatchesSequentiallyInternal(batchId, batches, currentIndex + 1, accumulatedResults, resultFunc);
  284. }
  285. });
  286. }
  287. function getBlockData(rpcClient, blockHash, txLimit, txOffset) {
  288. console.log("getBlockData: " + blockHash);
  289. return new Promise(function(resolve, reject) {
  290. client.cmd('getblock', blockHash, function(err2, result2, resHeaders2) {
  291. if (err2) {
  292. console.log("Error 3017hfwe0f: " + err2);
  293. reject(err2);
  294. return;
  295. }
  296. var txids = [];
  297. for (var i = txOffset; i < Math.min(txOffset + txLimit, result2.tx.length); i++) {
  298. txids.push(result2.tx[i]);
  299. }
  300. getRawTransactions(txids).then(function(transactions) {
  301. var txInputsByTransaction = {};
  302. var promises = [];
  303. for (var i = 0; i < transactions.length; i++) {
  304. var transaction = transactions[i];
  305. if (transaction) {
  306. promises.push(getTransactionInputs(client, transaction, 10));
  307. }
  308. }
  309. Promise.all(promises).then(function() {
  310. var results = arguments[0];
  311. for (var i = 0; i < results.length; i++) {
  312. var resultX = results[i];
  313. txInputsByTransaction[resultX.txid] = resultX.inputTransactions;
  314. }
  315. resolve({ getblock: result2, transactions: transactions, txInputsByTransaction: txInputsByTransaction });
  316. });
  317. });
  318. });
  319. });
  320. }
  321. function getBalanceFromAddress(rpcClient, address) {
  322. console.log("getBalanceFromAddress: " + address);
  323. return new Promise(function(resolve, reject) {
  324. client.cmd("getaddressbalance", "\'{\"addresses\": [\"" + address + "\"]}\'", function(err2, result2, resHeaders2) {
  325. if (err2) {
  326. console.log("Error 3017hfwe0f: " + err2);
  327. reject(err2);
  328. return;
  329. }
  330. resolve(result);
  331. });
  332. });
  333. }
  334. module.exports = {
  335. getInfo: getInfo,
  336. getMiningInfo: getMiningInfo,
  337. getMempoolInfo: getMempoolInfo,
  338. getBlockByHeight: getBlockByHeight,
  339. getBlocksByHeight: getBlocksByHeight,
  340. getBlockByHash: getBlockByHash,
  341. getBalanceFromAddress: getBalanceFromAddress,
  342. getTransactionInputs: getTransactionInputs,
  343. getBlockData: getBlockData,
  344. getRawTransaction: getRawTransaction,
  345. getRawTransactions: getRawTransactions,
  346. getMempoolStats: getMempoolStats
  347. };