From cbcd5c5981d31ea9871ef2d1b6c9424c2bf0290d Mon Sep 17 00:00:00 2001 From: Harpagon210 Date: Fri, 28 Sep 2018 20:25:37 -0500 Subject: [PATCH] adding replay from blocks.log file --- .gitignore | 3 +- app.js | 207 ++++++++++++++++++++++++++++++---------------- libs/Replay.js | 59 +++++++++++++ package-lock.json | 12 ++- package.json | 3 +- 5 files changed, 210 insertions(+), 74 deletions(-) create mode 100644 libs/Replay.js diff --git a/.gitignore b/.gitignore index 8e74263..76c6326 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ examples data test/data *.key -*.cert \ No newline at end of file +*.cert +blocks.log diff --git a/app.js b/app.js index 42f3a8b..4cbb48d 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,7 @@ const nodeCleanup = require('node-cleanup'); const fs = require('fs-extra'); +const program = require('commander'); +const packagejson = require('./package.json'); const { JsonRPCServer } = require('./libs/JsonRPCServer'); const { chainId, @@ -12,79 +14,146 @@ const { const { SteemStreamer } = require('./libs/SteemStreamer'); const { Blockchain } = require('./libs/Blockchain'); const { Transaction } = require('./libs/Transaction'); +const { Replay } = require('./libs/Replay'); -// instantiate the blockchain -const steemContracts = new Blockchain(chainId, autosaveInterval, javascriptVMTimeout); - -console.log('Loading Blockchain...'); // eslint-disable-line -steemContracts.loadBlockchain(dataDirectory, databaseFilePath, (error) => { - if (error) { - console.error(error); // eslint-disable-line - } else { - console.log('Blockchain loaded'); // eslint-disable-line - - // start reading the Steem blockchain to get incoming transactions - const steemStreamer = new SteemStreamer(chainId, startSteemBlock); - steemStreamer.stream((result) => { - // the stream parsed transactions from the Steem blockchain - const { timestamp, transactions } = result; - // we create the transactions that will be processed by the sidechain - transactions.forEach((transaction) => { - steemContracts.createTransaction( - new Transaction( - transaction.refBlockNumber, - transaction.transactionId, - transaction.sender, - transaction.contractName, - transaction.contractAction, - transaction.contractPayload, - ), - ); - }); +program + .version(packagejson.version) + .option('-r, --replay [type]', 'replay the blockchain from [file|steemd]', /^(file|steemd)$/i) + .parse(process.argv); - // if there are transactions pending we produce a block - if (transactions.length > 0) { - steemContracts.producePendingTransactions(timestamp); - } - }); - - // JSON RPC Server instantiation - const jsonRPCServer = new JsonRPCServer(steemContracts); - jsonRPCServer.StartServer(); - - // execute actions before the app closes - nodeCleanup((exitCode, signal) => { - if (signal) { - console.log('Closing App... ', exitCode, signal); // eslint-disable-line - - let currentSteemBlock = steemStreamer.GetCurrentBlock(); - steemStreamer.StopStream(); - - steemContracts.saveBlockchain((err) => { - if (err) { - console.error(err); // eslint-disable-line - } else { - console.log('Blockchain saved'); // eslint-disable-line - } +if (program.replay !== undefined) { + // instantiate the blockchain + const steemContracts = new Blockchain(chainId, 0, javascriptVMTimeout); + + console.log('Loading Blockchain...'); // eslint-disable-line + steemContracts.loadBlockchain(dataDirectory, databaseFilePath, (error) => { + if (error) { + console.error(error); // eslint-disable-line + } else { + let nbBlocksReplayed = 0; + console.log('Blockchain loaded'); // eslint-disable-line - // check if the last streamed Steem block is not lower than the latest block processed - const latestBlock = steemContracts.getLatestBlock(); - if (currentSteemBlock < latestBlock.refSteemBlockNumber) { - currentSteemBlock = latestBlock.refSteemBlockNumber; + // instantiate the replay tool + const replay = new Replay(program.replay); + console.log(`Sarting replay from ${program.replay}`); // eslint-disable-line + replay.start((result) => { + if (result) { + const { timestamp, transactions, blockNumber } = result; + console.log(`Replaying block ${blockNumber}`); // eslint-disable-line + nbBlocksReplayed += 1; + // we create the transactions that will be processed by the sidechain + transactions.forEach((transaction) => { + steemContracts.createTransaction( + new Transaction( + transaction.refBlockNumber, + transaction.transactionId, + transaction.sender, + transaction.contract, + transaction.action, + transaction.payload, + ), + ); + }); + // if there are transactions pending we produce a block + if (transactions.length > 0) { + steemContracts.producePendingTransactions(timestamp); } + } else { + console.log(`Done replaying ${nbBlocksReplayed} blocks`); // eslint-disable-line + steemContracts.saveBlockchain((err) => { + if (err) { + console.error(err); // eslint-disable-line + } else { + console.log('Blockchain saved'); // eslint-disable-line + } - const config = fs.readJSONSync('./config.json'); - config.startSteemBlock = currentSteemBlock; - fs.writeJSONSync('./config.json', config); + const latestBlock = steemContracts.getLatestBlock(); - // calling process.exit() won't inform parent process of signal - process.kill(process.pid, signal); + const config = fs.readJSONSync('./config.json'); + config.startSteemBlock = latestBlock.refSteemBlockNumber; + fs.writeJSONSync('./config.json', config); + + // calling process.exit() won't inform parent process of signal + process.kill(process.pid); + }); + } + }); + } + }); +} else { + // instantiate the blockchain + const steemContracts = new Blockchain(chainId, autosaveInterval, javascriptVMTimeout); + + console.log('Loading Blockchain...'); // eslint-disable-line + steemContracts.loadBlockchain(dataDirectory, databaseFilePath, (error) => { + if (error) { + console.error(error); // eslint-disable-line + } else { + console.log('Blockchain loaded'); // eslint-disable-line + + // start reading the Steem blockchain to get incoming transactions + const steemStreamer = new SteemStreamer(chainId, startSteemBlock); + steemStreamer.stream((result) => { + // the stream parsed transactions from the Steem blockchain + const { timestamp, transactions } = result; + // we create the transactions that will be processed by the sidechain + transactions.forEach((transaction) => { + steemContracts.createTransaction( + new Transaction( + transaction.refBlockNumber, + transaction.transactionId, + transaction.sender, + transaction.contractName, + transaction.contractAction, + transaction.contractPayload, + ), + ); }); - nodeCleanup.uninstall(); // don't call cleanup handler again - return false; - } - - return true; - }); - } -}); + + // if there are transactions pending we produce a block + if (transactions.length > 0) { + steemContracts.producePendingTransactions(timestamp); + } + }); + + // JSON RPC Server instantiation + const jsonRPCServer = new JsonRPCServer(steemContracts); + jsonRPCServer.StartServer(); + + // execute actions before the app closes + nodeCleanup((exitCode, signal) => { + if (signal) { + console.log('Closing App... ', exitCode, signal); // eslint-disable-line + + let currentSteemBlock = steemStreamer.GetCurrentBlock(); + steemStreamer.StopStream(); + + steemContracts.saveBlockchain((err) => { + if (err) { + console.error(err); // eslint-disable-line + } else { + console.log('Blockchain saved'); // eslint-disable-line + } + + // check if the last streamed Steem block is not lower than the latest block processed + const latestBlock = steemContracts.getLatestBlock(); + if (currentSteemBlock < latestBlock.refSteemBlockNumber) { + currentSteemBlock = latestBlock.refSteemBlockNumber; + } + + const config = fs.readJSONSync('./config.json'); + config.startSteemBlock = currentSteemBlock; + fs.writeJSONSync('./config.json', config); + + // calling process.exit() won't inform parent process of signal + process.kill(process.pid, signal); + }); + nodeCleanup.uninstall(); // don't call cleanup handler again + return false; + } + + return true; + }); + } + }); +} diff --git a/libs/Replay.js b/libs/Replay.js new file mode 100644 index 0000000..62c51ed --- /dev/null +++ b/libs/Replay.js @@ -0,0 +1,59 @@ +const fs = require('fs'); +const readline = require('readline'); +const stream = require('stream'); + +class Replay { + constructor(type) { + this.type = type; + this.stop = false; + } + + start(callback) { + if (this.type === 'file') { + Replay.replayFile(callback); + } + } + + stop() { + this.stop = true; + } + + static replayFile(callback) { + let instream; + let outstream; + let rl; + + // make sure file exists + const fileName = './blocks.log'; + fs.stat(fileName, (err, stats) => { + if (!err && stats.isFile()) { + instream = fs.createReadStream(fileName); + outstream = new stream(); // eslint-disable-line new-cap + rl = readline.createInterface(instream, outstream); + + rl.on('line', (line) => { + if (line !== '') { + const block = JSON.parse(line); + if (block.blockNumber !== 0) { + callback({ + blockNumber: block.blockNumber, + // we timestamp the block with the Steem block timestamp + timestamp: block.timestamp, + transactions: block.transactions, + }); + } + } + }); + + rl.on('close', () => { + callback(null); + }); + } else { + // file does not exist, so callback with null + callback(null); + } + }); + } +} + +module.exports.Replay = Replay; diff --git a/package-lock.json b/package-lock.json index 0227ed5..8a1a3e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -396,9 +396,9 @@ "dev": true }, "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.18.0.tgz", + "integrity": "sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==" }, "concat-map": { "version": "0.0.1", @@ -1722,6 +1722,12 @@ "supports-color": "5.4.0" }, "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", diff --git a/package.json b/package.json index 162f657..bb3b136 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "steemsmartcontracts", - "version": "1.0.0", + "version": "0.0.1", "description": "", "main": "app.js", "scripts": { @@ -11,6 +11,7 @@ "license": "MIT", "dependencies": { "body-parser": "^1.18.3", + "commander": "^2.18.0", "cors": "^2.8.4", "crypto-js": "^3.1.9-1", "currency.js": "^1.1.4",