From 3c2c8b663b509d2c5f5082ce7d22250f56c36669 Mon Sep 17 00:00:00 2001 From: primersion <7452156+primersion@users.noreply.github.com> Date: Fri, 27 May 2022 00:21:05 +0200 Subject: [PATCH] keep transactions <= lastVerifiedBlockNumber - blocksTokeep and allow getBlockInfo and getTransactionInfo for light nodes again --- app.js | 6 ++---- libs/Block.js | 6 +++--- libs/Database.js | 46 ++++++++++++++++++---------------------- plugins/JsonRPCServer.js | 15 ++++--------- 4 files changed, 30 insertions(+), 43 deletions(-) diff --git a/app.js b/app.js index a25f03b..1bf7cd7 100644 --- a/app.js +++ b/app.js @@ -196,10 +196,8 @@ const initLightNode = async () => { } console.log('Initializing light node - this may take a while..'); - // cleanup already verified blocks - await database.cleanupBlocks(); - // cleanup transactions - await database.cleanupTransactions(); + // cleanup old blocks / transactions for light nodes + await database.cleanupLightNode(); }; // start streaming the Hive blockchain and produce the sidechain blocks accordingly diff --git a/libs/Block.js b/libs/Block.js index e6eb1c4..02823eb 100644 --- a/libs/Block.js +++ b/libs/Block.js @@ -109,15 +109,15 @@ class Block { * @param database * @returns {Promise} */ - async cleanupBlocks(database) { + async cleanupLightNode(database) { if (this.blockNumber % 100 === 0) { - await database.cleanupBlocks(); + await database.cleanupLightNode(); } } // produce the block (deploy a smart contract or execute a smart contract) async produceBlock(database, jsVMTimeout, mainBlock) { - await this.cleanupBlocks(database); + await this.cleanupLightNode(database); await this.blockAdjustments(database); const nbTransactions = this.transactions.length; diff --git a/libs/Database.js b/libs/Database.js index 1ed7bed..71734ef 100644 --- a/libs/Database.js +++ b/libs/Database.js @@ -222,9 +222,6 @@ class Database { } async getTransactionInfo(txid) { - if (this.lightNode) { - throw new Error('getTransactionInfo not available for light node'); - } const transactionsTable = this.database.collection('transactions'); const transaction = await transactionsTable.findOne({ _id: txid }, { session: this.session }); @@ -247,10 +244,6 @@ class Database { const finalBlock = block; finalBlock._id = await this.getNextSequence('chain'); // eslint-disable-line no-underscore-dangle await this.chain.insertOne(finalBlock, { session: this.session }); - // do not insert transactions for lightnode - if (this.lightNode) { - return; - } await this.addTransactions(finalBlock); } @@ -1028,48 +1021,51 @@ class Database { } /** - * Used by light nodes to cleanup (unneeded) blocks already verified + * Used by light nodes to cleanup (unneeded) blocks / transactions already verified * by witnesses <= lastVerifiedBlockNumber - blocksToKeep * @returns {Promise} */ - async cleanupBlocks() { + async cleanupLightNode() { if (!this.lightNode) { return; } const params = await this.findOne({ contract: 'witnesses', table: 'params', query: {} }); if (params && params.lastVerifiedBlockNumber) { + console.log(`cleaning up light node blocks and transactions`); const cleanupUntilBlock = params.lastVerifiedBlockNumber - 1 - this.blocksToKeep; - await this.chain.deleteMany({ $and: [{ _id: { $gt: 0 } }, { _id: { $lte: cleanupUntilBlock } }] }, { session: this.session }); + await this.cleanupBlocks(cleanupUntilBlock); + await this.cleanupTransactions(cleanupUntilBlock); } } + /** + * Used by light nodes to cleanup (unneeded) blocks already verified + * by witnesses <= lastVerifiedBlockNumber - blocksToKeep + * @param cleanupUntilBlock cleanup blocks with a smaller blockNumber + * @returns {Promise} + */ + async cleanupBlocks(cleanupUntilBlock) { + await this.chain.deleteMany({ $and: [{ _id: { $gt: 0 } }, { _id: { $lte: cleanupUntilBlock } }] }, { session: this.session }); + } + /** * Used by light nodes to cleanup (unneeded) transactions + * @param cleanupUntilBlock cleanup transactions with a smaller blockNumber * @returns {Promise} */ - async cleanupTransactions() { - if (!this.lightNode) { - return; - } - const transactionsTable = this.database.collection('transactions'); - await transactionsTable.drop({ session: this.session }); - await this.database.createCollection('transactions', { session: this.session }); + async cleanupTransactions(cleanupUntilBlock) { + await this.database.collection('transactions').deleteMany({ blockNumber: { $lte: cleanupUntilBlock } }, { session: this.session }); } /** * Checks if a node was a light node previously and returns true in case it was. Light nodes - * don't store transaction data, so the check simply checks if there are any transactions in + * drop transaction data after a certain time, so the check tries to get the first transaction. form * the database. * @returns {Promise} */ async wasLightNodeBefore() { - const transactionsTable = this.database.collection('transactions'); - const someTransaction = await transactionsTable.findOne({}, { session: this.session }); - if (someTransaction) { - // transaction table should be empty for a light node - return false; - } - return true; + const transaction = await this.getTransactionInfo(0); + return !transaction; } } diff --git a/plugins/JsonRPCServer.js b/plugins/JsonRPCServer.js index d36bb45..a850fdb 100644 --- a/plugins/JsonRPCServer.js +++ b/plugins/JsonRPCServer.js @@ -49,11 +49,10 @@ async function generateStatus() { // get the ssc chain id from config result.chainId = config.chainId; - - // check if node is a light node - if (config.lightNode) { - result.lightNode = true; - } + + // get light node config of the SSC node + result.lightNode = config.lightNode; + result.blocksToKeep = config.blocksToKeep; resolve(result); } catch (error) { @@ -73,9 +72,6 @@ function blockchainRPC() { } }, getBlockInfo: async (args, callback) => { - if (config.lightNode) { - throw new Error('getBlockInfo not available for light nodes'); - } try { const { blockNumber } = args; @@ -93,9 +89,6 @@ function blockchainRPC() { } }, getTransactionInfo: async (args, callback) => { - if (config.lightNode) { - throw new Error('getTransactionInfo not available for light nodes'); - } try { const { txid } = args;