From 6c223711f2f75217300bd365afd0f4ed6538b727 Mon Sep 17 00:00:00 2001 From: Harpagon210 Date: Tue, 25 Sep 2018 21:15:37 -0500 Subject: [PATCH] improving database performances --- libs/Blockchain.js | 14 ++++++------ libs/DBUtils.js | 50 +++++++++++++++++++++--------------------- libs/SmartContracts.js | 10 ++++----- test/test.js | 26 ++++++++++++++++++++++ 4 files changed, 63 insertions(+), 37 deletions(-) diff --git a/libs/Blockchain.js b/libs/Blockchain.js index 0b1c52a..5c0112f 100644 --- a/libs/Blockchain.js +++ b/libs/Blockchain.js @@ -79,7 +79,7 @@ class Blockchain { // init the main tables this.chain = this.state.database.addCollection('chain'); - this.state.database.addCollection('contracts'); + this.state.database.addCollection('contracts', { indices: ['name'] }); // insert the genesis block this.chain.insert(Blockchain.createGenesisBlock(this.chainId)); @@ -108,7 +108,7 @@ class Blockchain { // get the latest block of the blockchain getLatestBlock() { const { maxId } = this.chain; - return this.chain.findOne({ $loki: maxId }); + return this.chain.get(maxId); } // produce all the pending transactions, that will result in the creattion of a block @@ -183,7 +183,7 @@ class Blockchain { // init the main tables this.chain = this.state.database.addCollection('chain'); - this.state.database.addCollection('contracts'); + this.state.database.addCollection('contracts', { indices: ['name'] }); // insert the genesis block this.chain.insert(Blockchain.createGenesisBlock(this.chainId)); @@ -217,7 +217,7 @@ class Blockchain { if (Number.isInteger(blockNumber)) { // the $loki field starts from 1 so the block 0 has the id 1 // so to get the actual block we need to add 1 to blockNumber - return this.chain.findOne({ $loki: blockNumber + 1 }); + return this.chain.get(blockNumber + 1); } return null; @@ -231,7 +231,7 @@ class Blockchain { // find records in the contract table by using the query, returns empty array if no records found findInTable(contract, table, query, limit = 1000, offset = 0, index = '', descending = false) { return DBUtils.findInTable( - this.state, + this.state.database, contract, table, query, @@ -244,12 +244,12 @@ class Blockchain { // find one record in the table of a contract by using the query, returns nullrecord found findOneInTable(contract, table, query) { - return DBUtils.findOneInTable(this.state, contract, table, query); + return DBUtils.findOneInTable(this.state.database, contract, table, query); } // get the contract info (owner, code, tables available, etc...) getContract(contract) { - return DBUtils.getContract(this.state, contract); + return DBUtils.getContract(this.state.database, contract); } } diff --git a/libs/DBUtils.js b/libs/DBUtils.js index e405528..2777206 100644 --- a/libs/DBUtils.js +++ b/libs/DBUtils.js @@ -1,13 +1,13 @@ class DBUtils { /** * Add a table to the database - * @param {Object} state state of the blockchain + * @param {Object} database database of the blockchain * @param {String} contractName name of the contract * @param {String} tableName name of the table * @param {Array} indexes array of string containing the name of the indexes to create * @returns {Object} returns the contract info if it exists, null otherwise */ - static createTable(state, contractName, tableName, indexes = []) { + static createTable(database, contractName, tableName, indexes = []) { const RegexLetters = /^[a-zA-Z_]+$/; // check that the params are correct @@ -19,23 +19,23 @@ class DBUtils { const finalTableName = `${contractName}_${tableName}`; // get the table from the database - const table = state.database.getCollection(finalTableName); + const table = database.getCollection(finalTableName); if (table) return table; // if it doesn't exist, create it (with the binary indexes) - return state.database.addCollection(finalTableName, { indices: indexes }); + return database.addCollection(finalTableName, { indices: indexes }); } /** * Get the information of a contract (owner, source code, etc...) - * @param {Object} state state of the blockchain + * @param {Object} database database of the blockchain * @param {String} contract name of the contract * @returns {Object} returns the contract info if it exists, null otherwise */ - static getContract(state, contract) { + static getContract(database, contract) { if (contract && typeof contract === 'string') { - const contracts = state.database.getCollection('contracts'); + const contracts = database.getCollection('contracts'); const contractInDb = contracts.findOne({ name: contract }); if (contractInDb) { @@ -48,7 +48,7 @@ class DBUtils { /** * retrieve records from the table of a contract - * @param {Object} state state of the blockchain + * @param {Object} database database of the blockchain * @param {String} contract contract name * @param {String} table table name * @param {JSON} query query to perform on the table @@ -58,22 +58,22 @@ class DBUtils { * @param {Boolean} descending the records set is sorted ascending if false, descending if true * @returns {Array} returns an array of objects if records found, an empty array otherwise */ - static findInTable(state, contract, table, query, limit = 1000, offset = 0, index = '', descending = false) { + static findInTable(database, contract, table, query, limit = 1000, offset = 0, index = '', descending = false) { if (contract && typeof contract === 'string' - && table && typeof table === 'string' - && query && typeof query === 'object' - && typeof index === 'string' - && typeof descending === 'boolean' - && Number.isInteger(limit) - && Number.isInteger(offset) - && limit > 0 && limit <= 1000 - && offset >= 0) { - const contractInDb = DBUtils.getContract(state, contract); + && table && typeof table === 'string' + && query && typeof query === 'object' + && typeof index === 'string' + && typeof descending === 'boolean' + && Number.isInteger(limit) + && Number.isInteger(offset) + && limit > 0 && limit <= 1000 + && offset >= 0) { + const contractInDb = DBUtils.getContract(database, contract); if (contractInDb) { const finalTableName = `${contract}_${table}`; if (contractInDb.tables.includes(finalTableName)) { - const tableData = state.database.getCollection(finalTableName); + const tableData = database.getCollection(finalTableName); // if there is an index passed, check if it exists if (index !== '' && tableData.binaryIndices[index] !== undefined) { @@ -99,22 +99,22 @@ class DBUtils { /** * retrieve a record from the table of a contract - * @param {Object} state state of the blockchain + * @param {Object} database database of the blockchain * @param {String} contract contract name * @param {String} table table name * @param {JSON} query query to perform on the table * @returns {Object} returns a record if it exists, null otherwise */ - static findOneInTable(state, contract, table, query) { + static findOneInTable(database, contract, table, query) { if (contract && typeof contract === 'string' - && table && typeof table === 'string' - && query && typeof query === 'object') { - const contractInDb = DBUtils.getContract(state, contract); + && table && typeof table === 'string' + && query && typeof query === 'object') { + const contractInDb = DBUtils.getContract(database, contract); if (contractInDb) { const finalTableName = `${contract}_${table}`; if (contractInDb.tables.includes(finalTableName)) { - const tableData = state.database.getCollection(finalTableName); + const tableData = database.getCollection(finalTableName); return tableData.findOne(query); } } diff --git a/libs/SmartContracts.js b/libs/SmartContracts.js index c2c209a..4d4cb47 100644 --- a/libs/SmartContracts.js +++ b/libs/SmartContracts.js @@ -57,7 +57,7 @@ class SmartContracts { const db = { // createTable is only available during the smart contract deployment createTable: (tableName, indexes = []) => { - const table = DBUtils.createTable(state, name, tableName, indexes); + const table = DBUtils.createTable(state.database, name, tableName, indexes); if (table) { // add the table name to the list of table available for this contract const finalTableName = `${name}_${tableName}`; @@ -76,7 +76,7 @@ class SmartContracts { index = '', descending = false, ) => DBUtils.findInTable( - state, + state.database, contractName, table, query, @@ -87,7 +87,7 @@ class SmartContracts { ), // perform a query on the tables of other smart contracts findOneInTable: (contractName, table, query) => DBUtils.findOneInTable( - state, + state.database, contractName, table, query, @@ -235,7 +235,7 @@ class SmartContracts { index = '', descending = false, ) => DBUtils.findInTable( - state, + state.database, contractName, table, query, @@ -246,7 +246,7 @@ class SmartContracts { ), // perform a query on the tables of other smart contracts findOneInTable: (contractName, table, query) => DBUtils.findOneInTable( - state, + state.database, contractName, table, query, diff --git a/test/test.js b/test/test.js index 6966e85..bf4d042 100644 --- a/test/test.js +++ b/test/test.js @@ -184,6 +184,32 @@ describe('Blockchain', function () { assert.equal(user.id, 'Harpagon'); }); }); + + it('should get the genesis block', function () { + cleanDataFolder(); + + // all the variables that we needed are now ready, we can deploy the smart contract + const steemSmartContracts = new Blockchain('testChainId', 0, 10000); + steemSmartContracts.loadBlockchain('./test/data/', 'database.db', (error) => { + assert.equal(steemSmartContracts.getBlockInfo(0).blockNumber, 0); + }); + }); + + it('should get the latest block', function () { + cleanDataFolder(); + + // all the variables that we needed are now ready, we can deploy the smart contract + const steemSmartContracts = new Blockchain('testChainId', 0, 10000); + + steemSmartContracts.loadBlockchain('./test/data/', 'database.db', (error) => { + steemSmartContracts.createTransaction(new Transaction(123456789, 'TXID1234', 'Harpagon', 'contract', 'deploy', '')); + steemSmartContracts.producePendingTransactions('2018-06-01T00:00:00'); + steemSmartContracts.createTransaction(new Transaction(123456789, 'TXID1234', 'Harpagon', 'contract', 'deploy', '')); + steemSmartContracts.producePendingTransactions('2018-06-01T00:00:00'); + + assert.equal(steemSmartContracts.getLatestBlock().blockNumber, 2); + }); + }); });