diff --git a/app/lib/blockchain/BasicBlockchain.ts b/app/lib/blockchain/BasicBlockchain.ts deleted file mode 100644 index 40cd0d668fb5fd2c1d71c06539038ec22ff4cea0..0000000000000000000000000000000000000000 --- a/app/lib/blockchain/BasicBlockchain.ts +++ /dev/null @@ -1,71 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -"use strict" -import {BlockchainOperator} from "./interfaces/BlockchainOperator" - -export class BasicBlockchain { - - constructor(private op:BlockchainOperator) { - } - - /** - * Adds a block at the end of the blockchain. - */ - pushBlock(b:any) { - return this.op.store(b) - } - - /** - * Get the block identified by `number` - * @param number block ID. - * @returns {*} Promise<Block> - */ - getBlock(number:number) { - return this.op.read(number) - } - - /** - * Get the nth block from the top of the blockchain. - * @param index Index from top. Defaults to `0`. E.g. `0` = HEAD, `1` = HEAD~1, etc. - * @returns {*} Promise<Block> - */ - head(index = 0) { - return this.op.head(index) - } - - /** - * Blockchain size, in number of blocks. - * @returns {*} Size. - */ - height() { - return this.op.height() - } - - /** - * Get the (n+1)th blocks top blocks of the blockchain, ordered by number ascending. - * @param n Quantity from top. E.g. `1` = [HEAD], `3` = [HEAD, HEAD~1, HEAD~2], etc. - * @returns {*} Promise<Block> - */ - headRange(n:number) { - return this.op.headRange(n) - } - - /** - * Pops the blockchain HEAD. - * @returns {*} Promise<Block> The reverted block. - */ - revertHead() { - return this.op.revertHead() - } -} diff --git a/app/lib/blockchain/DuniterBlockchain.ts b/app/lib/blockchain/DuniterBlockchain.ts index 6f4305c04a59c1f472f4024e7603cebb1e9e77ea..1c040261370cced138fce1e83fce361127576f88 100644 --- a/app/lib/blockchain/DuniterBlockchain.ts +++ b/app/lib/blockchain/DuniterBlockchain.ts @@ -11,9 +11,7 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -import {MiscIndexedBlockchain} from "./MiscIndexedBlockchain" import {FullIindexEntry, IindexEntry, IndexEntry, Indexer, MindexEntry, SindexEntry} from "../indexer" -import {BlockchainOperator} from "./interfaces/BlockchainOperator" import {ConfDTO} from "../dto/ConfDTO" import {BlockDTO} from "../dto/BlockDTO" import {DBHead} from "../db/DBHead" @@ -32,11 +30,7 @@ import {NewLogger} from "../logger" const _ = require('underscore') -export class DuniterBlockchain extends MiscIndexedBlockchain { - - constructor(blockchainStorage:BlockchainOperator, dal:FileDAL) { - super(blockchainStorage, dal.mindexDAL, dal.iindexDAL, dal.sindexDAL, dal.cindexDAL) - } +export class DuniterBlockchain { static async checkBlock(block:BlockDTO, withPoWAndSignature:boolean, conf: ConfDTO, dal:FileDAL) { const index = Indexer.localIndex(block, conf) @@ -186,7 +180,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { return { index, HEAD } } - async pushTheBlock(obj:BlockDTO, index:IndexEntry[], HEAD:DBHead | null, conf:ConfDTO, dal:FileDAL, logger:any) { + static async pushTheBlock(obj:BlockDTO, index:IndexEntry[], HEAD:DBHead | null, conf:ConfDTO, dal:FileDAL, logger:any) { const start = Date.now(); const block = BlockDTO.fromJSONObject(obj) try { @@ -213,7 +207,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { // await supra.recordIndex(index) } - async saveBlockData(current:DBBlock|null, block:BlockDTO, conf:ConfDTO, dal:FileDAL, logger:any, index:IndexEntry[], HEAD:DBHead | null) { + static async saveBlockData(current:DBBlock|null, block:BlockDTO, conf:ConfDTO, dal:FileDAL, logger:any, index:IndexEntry[], HEAD:DBHead | null) { if (block.number == 0) { await this.saveParametersForRoot(block, conf, dal); } @@ -275,7 +269,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { return dbb } - async saveParametersForRoot(block:BlockDTO, conf:ConfDTO, dal:FileDAL) { + static async saveParametersForRoot(block:BlockDTO, conf:ConfDTO, dal:FileDAL) { if (block.parameters) { const bconf = BlockDTO.getConf(block) conf.c = bconf.c; @@ -305,7 +299,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - async createNewcomers(iindex:IindexEntry[], dal:FileDAL, logger:any) { + static async createNewcomers(iindex:IindexEntry[], dal:FileDAL, logger:any) { for (const i of iindex) { if (i.op == CommonConstants.IDX_CREATE) { const entry = i as FullIindexEntry @@ -319,7 +313,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - async updateMembers(block:BlockDTO, dal:FileDAL) { + static async updateMembers(block:BlockDTO, dal:FileDAL) { // Joiners (come back) for (const inlineMS of block.joiners) { let ms = MembershipDTO.fromInline(inlineMS) @@ -338,7 +332,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - async updateWallets(sindex:SindexEntry[], aDal:any, reverse = false) { + static async updateWallets(sindex:SindexEntry[], aDal:any, reverse = false) { const differentConditions = _.uniq(sindex.map((entry) => entry.conditions)) for (const conditions of differentConditions) { const creates = _.filter(sindex, (entry:SindexEntry) => entry.conditions === conditions && entry.op === CommonConstants.IDX_CREATE) @@ -356,7 +350,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - async revertBlock(number:number, hash:string, dal:FileDAL) { + static async revertBlock(number:number, hash:string, dal:FileDAL) { const blockstamp = [number, hash].join('-'); const block = await dal.getBlockByBlockstampOrNull(blockstamp) @@ -406,7 +400,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { return block } - async undoMembersUpdate(blockstamp:string, dal:FileDAL) { + static async undoMembersUpdate(blockstamp:string, dal:FileDAL) { const joiners = await dal.iindexDAL.getWrittenOn(blockstamp); for (const entry of joiners) { // Undo 'join' which can be either newcomers or comebackers @@ -437,7 +431,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - async undoDeleteTransactions(block:DBBlock, dal:FileDAL) { + static async undoDeleteTransactions(block:DBBlock, dal:FileDAL) { for (const obj of block.transactions) { obj.currency = block.currency; let tx = TransactionDTO.fromJSONObject(obj) @@ -469,7 +463,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { * @param block Block in which are contained the certifications to remove from sandbox. * @param dal The DAL */ - async removeMembershipsFromSandbox(block:BlockDTO, dal:FileDAL) { + static async removeMembershipsFromSandbox(block:BlockDTO, dal:FileDAL) { const mss = block.joiners.concat(block.actives).concat(block.leavers); for (const inlineMS of mss) { let ms = MembershipDTO.fromInline(inlineMS) @@ -480,14 +474,14 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - async computeToBeRevoked(mindex:MindexEntry[], dal:FileDAL) { + static async computeToBeRevoked(mindex:MindexEntry[], dal:FileDAL) { const revocations = _.filter(mindex, (entry:MindexEntry) => entry.revoked_on); for (const revoked of revocations) { await dal.setRevoked(revoked.pub) } } - async deleteTransactions(block:BlockDTO, dal:FileDAL) { + static async deleteTransactions(block:BlockDTO, dal:FileDAL) { for (const obj of block.transactions) { obj.currency = block.currency; const tx = TransactionDTO.fromJSONObject(obj) @@ -496,7 +490,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - updateBlocksComputedVars( + static updateBlocksComputedVars( current:{ unitbase:number, monetaryMass:number }|null, block:{ number:number, unitbase:number, dividend:number|null, membersCount:number, monetaryMass:number }): void { // Unit Base @@ -548,7 +542,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { return dal.pushStats(stats); } - async pushSideBlock(obj:BlockDTO, dal:FileDAL, logger:any) { + static async pushSideBlock(obj:BlockDTO, dal:FileDAL, logger:any) { const start = Date.now(); const block = DBBlock.fromBlockDTO(BlockDTO.fromJSONObject(obj)) block.fork = true; @@ -562,11 +556,4 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { throw err; } } - - async revertHead() { - const indexRevert = super.indexRevert - const headf = super.head - const head = await headf() - await indexRevert(head.number) - } } diff --git a/app/lib/blockchain/IndexedBlockchain.ts b/app/lib/blockchain/IndexedBlockchain.ts deleted file mode 100644 index dd81222d526e201922e47a47cdef90f666c212ba..0000000000000000000000000000000000000000 --- a/app/lib/blockchain/IndexedBlockchain.ts +++ /dev/null @@ -1,139 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -"use strict" -import {BasicBlockchain} from "./BasicBlockchain" -import {IndexOperator} from "./interfaces/IndexOperator" -import {BlockchainOperator} from "./interfaces/BlockchainOperator" - -const _ = require('underscore') - -export class IndexedBlockchain extends BasicBlockchain { - - private initIndexer: Promise<void> - - constructor(bcOperations: BlockchainOperator, private indexOperations: IndexOperator, private numberField: string, private pkFields: any) { - super(bcOperations) - this.initIndexer = indexOperations.initIndexer(pkFields) - } - - async recordIndex(index: { [index: string]: any }) { - // Wait indexer init - await this.initIndexer - - return this.indexOperations.recordIndex(index) - } - - async indexTrim(maxNumber:number) { - - // Wait indexer init - await this.initIndexer - - const subIndexes = await this.indexOperations.getSubIndexes() - // Trim the subIndexes - const records: { [index: string]: any } = {} - for (const subIndex of subIndexes) { - records[subIndex] = [] - const pks = typeof this.pkFields[subIndex].pk !== 'string' && this.pkFields[subIndex].pk.length ? Array.from(this.pkFields[subIndex].pk) : [this.pkFields[subIndex].pk] - const rm = this.pkFields[subIndex].remove - let potentialRecords = await this.indexOperations.findTrimable(subIndex, this.numberField, maxNumber) - potentialRecords = reduceBy(potentialRecords, pks) - for (const potential of potentialRecords) { - const subCriteriasRowsToDelete = criteriasFromPks(pks, potential) - subCriteriasRowsToDelete[this.numberField] = { $lt: maxNumber } - const rowsToReduce = await this.indexOperations.findWhere(subIndex, subCriteriasRowsToDelete) - // No reduction if 1 line to delete - if (rowsToReduce.length > 1) { - const reduced = reduce(rowsToReduce) - const subCriteriasRowsToKeep = criteriasFromPks(pks, potential) - subCriteriasRowsToKeep[this.numberField] = { $gte: maxNumber } - const toKeep = await this.indexOperations.findWhere(subIndex, subCriteriasRowsToKeep) - const subCriteriasAllRowsOfObject = criteriasFromPks(pks, potential) - await this.indexOperations.removeWhere(subIndex, subCriteriasAllRowsOfObject) - // Add the reduced row + rows to keep - if (!rm || !reduced[rm]) { - records[subIndex] = records[subIndex].concat([reduced]).concat(toKeep) - } - } - } - } - await this.recordIndex(records) - return Promise.resolve() - } - - async indexCount(indexName: string, criterias: { [index: string]: any }) { - - // Wait indexer init - await this.initIndexer - - const records = await this.indexOperations.findWhere(indexName, criterias) - return records.length - } - - async indexReduce(indexName: string, criterias: { [index: string]: any }) { - - // Wait indexer init - await this.initIndexer - - const records = await this.indexOperations.findWhere(indexName, criterias) - return reduce(records) - } - - async indexReduceGroupBy(indexName: string, criterias: { [index: string]: any }, properties: string[]) { - - // Wait indexer init - await this.initIndexer - - const records = await this.indexOperations.findWhere(indexName, criterias) - return reduceBy(records, properties) - } - - async indexRevert(blockNumber:number) { - const subIndexes = await this.indexOperations.getSubIndexes() - for (const subIndex of subIndexes) { - const removeCriterias: { [index: string]: any } = {} - removeCriterias[this.numberField] = blockNumber - await this.indexOperations.removeWhere(subIndex, removeCriterias) - } - } -} - -function reduce(records: any[]) { - return records.reduce((obj, record) => { - const keys = Object.keys(record); - for (const k of keys) { - if (record[k] !== undefined && record[k] !== null) { - obj[k] = record[k]; - } - } - return obj; - }, {}); -} - -function reduceBy(reducables: any[], properties: string[]) { - const reduced = reducables.reduce((map, entry) => { - const id = properties.map((prop) => entry[prop]).join('-'); - map[id] = map[id] || []; - map[id].push(entry); - return map; - }, {}); - return _.values(reduced).map((rows: any[]) => reduce(rows)) -} - -function criteriasFromPks(pks: string[], values: any): { [index: string]: any } { - const criterias: { [index: string]: any } = {} - for (const key of pks) { - criterias[key] = values[key] - } - return criterias -} diff --git a/app/lib/blockchain/MiscIndexedBlockchain.ts b/app/lib/blockchain/MiscIndexedBlockchain.ts deleted file mode 100644 index 5f881ba0d0dad2f6dea1b27a734c5c4949e02cc3..0000000000000000000000000000000000000000 --- a/app/lib/blockchain/MiscIndexedBlockchain.ts +++ /dev/null @@ -1,50 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -"use strict" -import {IndexedBlockchain} from "./IndexedBlockchain" -import {SQLIndex} from "./SqlIndex" -import {BlockchainOperator} from "./interfaces/BlockchainOperator" - -export class MiscIndexedBlockchain extends IndexedBlockchain { - - constructor(blockchainStorage: BlockchainOperator, mindexDAL:any, iindexDAL:any, sindexDAL:any, cindexDAL:any) { - super(blockchainStorage, new SQLIndex(null, { - m_index: { handler: mindexDAL }, - i_index: { handler: iindexDAL }, - s_index: { - handler: sindexDAL, - findTrimable: (maxNumber:number) => sindexDAL.query('SELECT * FROM s_index WHERE consumed AND writtenOn < ?', [maxNumber]) - }, - c_index: { - handler: cindexDAL, - findTrimable: (maxNumber:number) => cindexDAL.query('SELECT * FROM c_index WHERE expired_on > 0 AND writtenOn < ?', [maxNumber]) - } - }), 'writtenOn', { - m_index: { - pk: ['pub'] - }, - i_index: { - pk: ['pub'] - }, - s_index: { - pk: ['identifier', 'pos'], - remove: 'consumed' - }, - c_index: { - pk: ['issuer', 'receiver', 'created_on'], - remove: 'expired_on' - } - }) - } -} diff --git a/app/lib/blockchain/SqlBlockchain.ts b/app/lib/blockchain/SqlBlockchain.ts deleted file mode 100644 index 84d2f5b97fac12abe67e335d692e1a8845ff58c0..0000000000000000000000000000000000000000 --- a/app/lib/blockchain/SqlBlockchain.ts +++ /dev/null @@ -1,76 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -"use strict" -import {BlockchainOperator} from "./interfaces/BlockchainOperator" - -const indexer = require('../../lib/indexer').Indexer - -export class SQLBlockchain implements BlockchainOperator { - - constructor(private dal: { bindexDAL:any }) { - } - - store(b: any): Promise<any> { - return this.dal.bindexDAL.saveEntity(b) - } - - read(i: number): Promise<any> { - return this.dal.bindexDAL.sqlFindOne({ number: i }) - } - - async head(n = 0): Promise<any> { - /** - * IMPORTANT NOTICE - * ---------------- - * - * There is a difference between the protocol's HEAD (P_HEAD) and the database's HEAD (DB_HEAD). The relation is: - * - * DB_HEAD~<i> = P_HEAD~<i+1> - * - * In this class methods, we expose DB_HEAD logic. But the data is stored/retrieved by DAL objects using P_HEAD logic. - * - * So if we want DB_HEAD~0 for example, we must ask P_HEAD~(0+1). The DAL object will then retrieve P_HEAD~1, which - * is the latest stored block in the blockchain. - * - * Note: the DAL object cannot retrieve P_HEAD~0, this value does not exist and refers to the potential incoming block. - * - * Why this behavior? - * ------------------ - * - * Because the DAL was wrongly coded. It will be easy to fix this problem once indexer.js will only use **this class' - * methods**. Then, we will be able to replace (n + 1) by just (n), and replace also the complementary behavior in - * the DAL (BIndexDAL). - */ - return this.dal.bindexDAL.head(n + 1) - } - - async height(): Promise<number> { - const head = await this.dal.bindexDAL.head(1) // We do not use head(0). See the above notice. - if (head) { - return head.number + 1 - } else { - return 0 - } - } - - headRange(m: number): Promise<any[]> { - return this.dal.bindexDAL.range(1, m) // We do not use range(0, m). See the above notice. - } - - async revertHead(): Promise<any> { - const head = await this.dal.bindexDAL.head(1) // We do not use head(0). See the above notice. - await this.dal.bindexDAL.removeBlock(head.number) - return head - } -} diff --git a/app/lib/blockchain/SqlIndex.ts b/app/lib/blockchain/SqlIndex.ts deleted file mode 100644 index 53cb379c94934e700abc4bab8097691533085db4..0000000000000000000000000000000000000000 --- a/app/lib/blockchain/SqlIndex.ts +++ /dev/null @@ -1,86 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -"use strict" -import {IndexOperator} from "./interfaces/IndexOperator" -import {AbstractIndex} from "../dal/sqliteDAL/AbstractIndex"; - -const _ = require('underscore') - -export class SQLIndex implements IndexOperator { - - private indexes: { [k:string]: any } = {} - - constructor(private db:any, private definitions: any) { - } - - async initIndexer(pkFields: any): Promise<void> { - const keys = _.keys(pkFields) - for (const k of keys) { - if (this.definitions[k].handler) { - // External table: managed by another object - this.indexes[k] = this.definitions[k].handler - } else { - // Internal table: managed here - const indexTable = new AbstractIndex<any>(this.db, k, [], this.definitions[k].fields, [], this.definitions[k].booleans) - this.indexes[k] = indexTable - indexTable.init = () => { - return indexTable.exec('BEGIN;' + - 'CREATE TABLE IF NOT EXISTS ' + indexTable.table + ' (' + - this.definitions[k].sqlFields.join(',') + - ');' + - 'COMMIT;') - } - await indexTable.init() - } - } - } - - getSubIndexes(): Promise<string[]> { - return Promise.resolve(_.keys(this.indexes)) - } - - findTrimable(subIndex: string, numberField: string, maxNumber: number): Promise<any[]> { - if (this.definitions[subIndex].findTrimable) { - return this.definitions[subIndex].findTrimable(maxNumber) - } else { - const criterias:any = {} - criterias[numberField] = { $lt: maxNumber } - return this.indexes[subIndex].sqlFind(criterias) - } - } - - removeWhere(subIndex: string, criterias: {}): Promise<void> { - if (!this.indexes[subIndex]) { - return Promise.resolve() - } - return this.indexes[subIndex].sqlRemoveWhere(criterias) - } - - async recordIndex(index: any): Promise<void> { - const subIndexes = _.keys(index) - // Feed the this.indexes - for (const subIndex of subIndexes) { - await this.indexes[subIndex].insertBatch(index[subIndex]) - } - return Promise.resolve() - } - - - findWhere(subIndex: string, criterias: {}): Promise<any[]> { - if (!this.indexes[subIndex]) { - return Promise.resolve([]) - } - return this.indexes[subIndex].sqlFind(criterias) - } -} diff --git a/app/lib/blockchain/interfaces/BlockchainOperator.ts b/app/lib/blockchain/interfaces/BlockchainOperator.ts deleted file mode 100644 index f3f50177b91ea18f8598742f516bc76f601c4b55..0000000000000000000000000000000000000000 --- a/app/lib/blockchain/interfaces/BlockchainOperator.ts +++ /dev/null @@ -1,51 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -"use strict" - -export interface BlockchainOperator { - - /** - * Pushes a new block at the top of the blockchain. - * @param b Block. - */ - store(b:any):Promise<any> - - /** - * Reads the block at index `i`. - * @param i Block number. - */ - read(i:number):Promise<any> - - /** - * Reads the block at index `n` from the top of the blockchain. - * @param n Reverse index. - */ - head(n:number):Promise<any> - - /** - * Gives the number of blocks in the blockchain. - */ - height():Promise<number> - - /** - * Reads the blocks from head(0) to head(m) - * @param m Quantity. - */ - headRange(m:number):Promise<any[]> - - /** - * Pops the top block. - */ - revertHead():Promise<any> -} diff --git a/app/lib/blockchain/interfaces/IndexOperator.ts b/app/lib/blockchain/interfaces/IndexOperator.ts deleted file mode 100644 index 57b475d630fa753a04713bd904b7d29b89bc8951..0000000000000000000000000000000000000000 --- a/app/lib/blockchain/interfaces/IndexOperator.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -"use strict" - -export interface IndexOperator { - - initIndexer(pkFields: any): Promise<void>, - - getSubIndexes(): Promise<string[]>, - - findWhere(subIndex: string, criterias: {}): Promise<any[]>, - - findTrimable(subIndex: string, numberField: string, maxNumber: number): Promise<any[]>, - - removeWhere(subIndex: string, criterias: {}): Promise<void>, - - recordIndex(index: any): Promise<void> -} diff --git a/app/lib/computation/BlockchainContext.ts b/app/lib/computation/BlockchainContext.ts index 4354b131a199b8b47b57421368aac7cd2848505c..b33f4a7ace0b891835300802f7a6d81fbf8b3735 100644 --- a/app/lib/computation/BlockchainContext.ts +++ b/app/lib/computation/BlockchainContext.ts @@ -108,10 +108,9 @@ export class BlockchainContext { return local_vHEAD.issuerDiff; } - setConfDAL(newConf: any, newDAL: any, theBlockchain: DuniterBlockchain, theQuickSynchronizer: QuickSynchronizer): void { + setConfDAL(newConf: any, newDAL: any, theQuickSynchronizer: QuickSynchronizer): void { this.dal = newDAL; this.conf = newConf; - this.blockchain = theBlockchain this.quickSynchronizer = theQuickSynchronizer this.logger = require('../logger').NewLogger(this.dal.profile); } @@ -121,20 +120,20 @@ export class BlockchainContext { } private async addBlock(obj: BlockDTO, index: any = null, HEAD: DBHead | null = null): Promise<any> { - const block = await this.blockchain.pushTheBlock(obj, index, HEAD, this.conf, this.dal, this.logger) + const block = await DuniterBlockchain.pushTheBlock(obj, index, HEAD, this.conf, this.dal, this.logger) this.vHEAD_1 = this.vHEAD = null return block } async addSideBlock(obj:BlockDTO): Promise<BlockDTO> { - const dbb = await this.blockchain.pushSideBlock(obj, this.dal, this.logger) + const dbb = await DuniterBlockchain.pushSideBlock(obj, this.dal, this.logger) return dbb.toBlockDTO() } async revertCurrentBlock(): Promise<DBBlock> { const head_1 = await this.dal.bindexDAL.head(1); this.logger.debug('Reverting block #%s...', head_1.number); - const res = await this.blockchain.revertBlock(head_1.number, head_1.hash, this.dal) + const res = await DuniterBlockchain.revertBlock(head_1.number, head_1.hash, this.dal) // Invalidates the head, since it has changed. await this.refreshHead(); return res; diff --git a/app/lib/computation/QuickSync.ts b/app/lib/computation/QuickSync.ts index 071e07027bb414d2eb4ae848facb416b0fd1cc3c..f2f94a5ba7bd4f554486248948213918550a44b6 100644 --- a/app/lib/computation/QuickSync.ts +++ b/app/lib/computation/QuickSync.ts @@ -11,7 +11,6 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -"use strict" import {DuniterBlockchain} from "../blockchain/DuniterBlockchain"; import {BlockDTO} from "../dto/BlockDTO"; import {DBTransaction} from "../db/DBTransaction"; @@ -50,7 +49,7 @@ const sync_memoryDAL:AccountsGarbagingDAL = { export class QuickSynchronizer { - constructor(private blockchain:DuniterBlockchain, private conf: any, private dal:FileDAL, private logger: any) { + constructor(private conf: any, private dal:FileDAL, private logger: any) { } async saveBlocksInMainBranch(blocks: BlockDTO[]): Promise<void> { @@ -73,7 +72,7 @@ export class QuickSynchronizer { for (const block of blocks) { block.fork = false; const current:BlockDTO|null = block.number > 0 ? await getBlock(block.number - 1) : null - this.blockchain.updateBlocksComputedVars(current, block) + DuniterBlockchain.updateBlocksComputedVars(current, block) } // Transactions recording await this.updateTransactionsForBlocks(blocks, getBlockByNumberAndHash); @@ -107,7 +106,7 @@ export class QuickSynchronizer { // VERY FIRST: parameters, otherwise we compute wrong variables such as UDTime if (block.number == 0) { - await this.blockchain.saveParametersForRoot(block, this.conf, this.dal) + await DuniterBlockchain.saveParametersForRoot(block, this.conf, this.dal) } // The new kind of object stored @@ -140,7 +139,7 @@ export class QuickSynchronizer { } } - await this.blockchain.createNewcomers(local_iindex, this.dal, this.logger) + await DuniterBlockchain.createNewcomers(local_iindex, this.dal, this.logger) if (block.dividend || block.joiners.length @@ -191,7 +190,7 @@ export class QuickSynchronizer { sync_mindex = sync_mindex.concat(await Indexer.ruleIndexGenImplicitRevocation(HEAD, this.dal)); } // Update balances with UD + local garbagings - await this.blockchain.updateWallets(sync_sindex, sync_memoryDAL) + await DuniterBlockchain.updateWallets(sync_sindex, sync_memoryDAL) // --> Update links await this.dal.updateWotbLinks(local_cindex.concat(sync_cindex)); @@ -207,7 +206,7 @@ export class QuickSynchronizer { sync_sindex = []; // Create/Update nodes in wotb - await this.blockchain.updateMembers(block, this.dal) + await DuniterBlockchain.updateMembers(block, this.dal) } // Trim the bindex @@ -247,12 +246,12 @@ export class QuickSynchronizer { } if (block.number === 0) { - await this.blockchain.saveParametersForRoot(block, this.conf, this.dal) + await DuniterBlockchain.saveParametersForRoot(block, this.conf, this.dal) } // Last block: cautious mode to trigger all the INDEX expiry mechanisms const { index, HEAD } = await DuniterBlockchain.checkBlock(dto, constants.WITH_SIGNATURES_AND_POW, this.conf, this.dal) - await this.blockchain.pushTheBlock(dto, index, HEAD, this.conf, this.dal, this.logger) + await DuniterBlockchain.pushTheBlock(dto, index, HEAD, this.conf, this.dal, this.logger) // Clean temporary variables sync_bindex = []; diff --git a/app/lib/other_constants.ts b/app/lib/other_constants.ts index d10528e99d6325e1c5fe5ced474a1164f9795cfc..63162b599a680e000c9798f7b6f6397c4d6c25ae 100644 --- a/app/lib/other_constants.ts +++ b/app/lib/other_constants.ts @@ -13,7 +13,7 @@ export const OtherConstants = { - MUTE_LOGS_DURING_UNIT_TESTS: false, + MUTE_LOGS_DURING_UNIT_TESTS: true, SQL_TRACES: false, BC_EVENT: { diff --git a/app/lib/system/directory.ts b/app/lib/system/directory.ts index d0717051c95173a964ba3107e5ec18faf280d5a5..c40df48d959b343260ee1141b25156b478f43715 100644 --- a/app/lib/system/directory.ts +++ b/app/lib/system/directory.ts @@ -106,7 +106,7 @@ export const RealFS = (): FileSystem => { } export const MemFS = (initialTree:{ [folder:string]: { [file:string]: string }} = {}): FileSystem => { - return new QioFileSystem(require('q-io/fs-mock')(initialTree)) + return new QioFileSystem(require('q-io/fs-mock')(initialTree), true) } export const Directory = { diff --git a/app/service/BlockchainService.ts b/app/service/BlockchainService.ts index c9d5a7219f153030a6d28494ade4ced5882604b5..4e4e29e8d64b0c388b428b4db2c168e30f938961 100644 --- a/app/service/BlockchainService.ts +++ b/app/service/BlockchainService.ts @@ -29,6 +29,7 @@ import {LOCAL_RULES_FUNCTIONS} from "../lib/rules/local_rules" import {Switcher, SwitcherDao} from "../lib/blockchain/Switcher" import {OtherConstants} from "../lib/other_constants" import {DataErrors} from "../lib/common-libs/errors" +import {DuniterBlockchain} from "../lib/blockchain/DuniterBlockchain" "use strict"; @@ -141,8 +142,8 @@ export class BlockchainService extends FIFOService { this.dal = newDAL; this.conf = newConf; this.logger = require('../lib/logger').NewLogger(this.dal.profile) - this.quickSynchronizer = new QuickSynchronizer(this.server.blockchain, this.conf, this.dal, this.logger) - this.mainContext.setConfDAL(this.conf, this.dal, this.server.blockchain, this.quickSynchronizer) + this.quickSynchronizer = new QuickSynchronizer(this.conf, this.dal, this.logger) + this.mainContext.setConfDAL(this.conf, this.dal, this.quickSynchronizer) this.selfPubkey = newKeyPair.publicKey; } @@ -444,7 +445,7 @@ export class BlockchainService extends FIFOService { // This method is called by duniter-crawler 1.3.x saveParametersForRootBlock(block:BlockDTO) { - return this.server.blockchain.saveParametersForRoot(block, this.conf, this.dal) + return DuniterBlockchain.saveParametersForRoot(block, this.conf, this.dal) } async blocksBetween(from:number, count:number): Promise<DBBlock[]> { diff --git a/server.ts b/server.ts index 04137cba28e5a1720b0dc91a5ff7282cf6dcb681..ff02773dd610a8aef18f8af90314cee81d33aeaf 100644 --- a/server.ts +++ b/server.ts @@ -18,8 +18,6 @@ import {BlockchainService} from "./app/service/BlockchainService" import {TransactionService} from "./app/service/TransactionsService" import {ConfDTO} from "./app/lib/dto/ConfDTO" import {FileDAL, FileDALParams} from "./app/lib/dal/fileDAL" -import {DuniterBlockchain} from "./app/lib/blockchain/DuniterBlockchain" -import {SQLBlockchain} from "./app/lib/blockchain/SqlBlockchain" import * as stream from "stream" import {KeyGen, randomKey} from "./app/lib/common-libs/crypto/keyring" import {parsers} from "./app/lib/common-libs/parsers/index" @@ -198,8 +196,6 @@ export class Server extends stream.Duplex implements HookableServer { // Extract key pair this.keyPair = KeyGen(this.conf.pair.pub, this.conf.pair.sec); this.sign = (msg:string) => this.keyPair.sign(msg) - // Blockchain object - this.blockchain = new DuniterBlockchain(new SQLBlockchain(this.dal), this.dal); // Update services this.IdentityService.setConfDAL(this.conf, this.dal) this.MembershipService.setConfDAL(this.conf, this.dal) diff --git a/test/blockchain/basic-blockchain.ts b/test/blockchain/basic-blockchain.ts deleted file mode 100644 index 7acfea13f574b312a7f94e52e90ab7dfa839fd2a..0000000000000000000000000000000000000000 --- a/test/blockchain/basic-blockchain.ts +++ /dev/null @@ -1,174 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -import {BasicBlockchain} from "../../app/lib/blockchain/BasicBlockchain" -import {ArrayBlockchain} from "./lib/ArrayBlockchain" -import {SQLBlockchain} from "../../app/lib/blockchain/SqlBlockchain" -import {SQLiteDriver} from "../../app/lib/dal/drivers/SQLiteDriver" -import {BIndexDAL} from "../../app/lib/dal/sqliteDAL/index/BIndexDAL"; -import {MetaDAL} from "../../app/lib/dal/sqliteDAL/MetaDAL"; -import {ConfDTO} from "../../app/lib/dto/ConfDTO"; - -const assert = require('assert') - -let blockchain:BasicBlockchain, - emptyBlockchain:BasicBlockchain - -describe('Basic Memory Blockchain', () => { - - before(() => { - blockchain = new BasicBlockchain(new ArrayBlockchain()) - emptyBlockchain = new BasicBlockchain(new ArrayBlockchain()) - }) - - it('should be able to push 3 blocks and read them', async () => { - await blockchain.pushBlock({ name: 'A' }) - await blockchain.pushBlock({ name: 'B' }) - await blockchain.pushBlock({ name: 'C' }) - const HEAD0 = await blockchain.head() - const HEAD1 = await blockchain.head(1) - const HEAD2 = await blockchain.head(2) - const BLOCK0 = await blockchain.getBlock(0) - const BLOCK1 = await blockchain.getBlock(1) - const BLOCK2 = await blockchain.getBlock(2) - assert.equal(HEAD0.name, 'C') - assert.equal(HEAD1.name, 'B') - assert.equal(HEAD2.name, 'A') - assert.deepEqual(HEAD2, BLOCK0) - assert.deepEqual(HEAD1, BLOCK1) - assert.deepEqual(HEAD0, BLOCK2) - }) - - it('should be able to read a range', async () => { - const range1 = await blockchain.headRange(2) - assert.equal(range1.length, 2) - assert.equal(range1[0].name, 'C') - assert.equal(range1[1].name, 'B') - const range2 = await blockchain.headRange(6) - assert.equal(range2.length, 3) - assert.equal(range2[0].name, 'C') - assert.equal(range2[1].name, 'B') - assert.equal(range2[2].name, 'A') - }) - - it('should have a good height', async () => { - const height1 = await blockchain.height() - await blockchain.pushBlock({ name: 'D' }) - const height2 = await blockchain.height() - const height3 = await emptyBlockchain.height() - assert.equal(height1, 3) - assert.equal(height2, 4) - assert.equal(height3, 0) - }) - - it('should be able to revert blocks', async () => { - const reverted = await blockchain.revertHead() - const height2 = await blockchain.height() - assert.equal(height2, 3) - assert.equal(reverted.name, 'D') - }) - -}) - -describe.skip('Basic SQL Blockchain', () => { - - before(async () => { - - { - const db = new SQLiteDriver(':memory:') - - const bindexDAL = new BIndexDAL(db) - const metaDAL = new MetaDAL(db) - - await bindexDAL.init() - await metaDAL.init() - await metaDAL.exec('CREATE TABLE txs (id INTEGER null);') - await metaDAL.exec('CREATE TABLE idty (id INTEGER null);') - await metaDAL.exec('CREATE TABLE cert (id INTEGER null);') - await metaDAL.exec('CREATE TABLE membership (id INTEGER null);') - await metaDAL.exec('CREATE TABLE block (fork INTEGER null);') - await metaDAL.upgradeDatabase(ConfDTO.mock()); - - const dal = { bindexDAL } - - blockchain = new BasicBlockchain(new SQLBlockchain(dal)) - } - { - const db = new SQLiteDriver(':memory:') - - const bindexDAL = new BIndexDAL(db) - const metaDAL = new MetaDAL(db) - - await bindexDAL.init() - await metaDAL.init() - await metaDAL.exec('CREATE TABLE txs (id INTEGER null);') - await metaDAL.exec('CREATE TABLE idty (id INTEGER null);') - await metaDAL.exec('CREATE TABLE cert (id INTEGER null);') - await metaDAL.exec('CREATE TABLE membership (id INTEGER null);') - await metaDAL.exec('CREATE TABLE block (fork INTEGER null);') - await metaDAL.upgradeDatabase(ConfDTO.mock()); - - const dal = { bindexDAL } - - emptyBlockchain = new BasicBlockchain(new SQLBlockchain(dal)) - } - }) - - it('should be able to push 3 blocks and read them', async () => { - await blockchain.pushBlock({ number: 0, version: 1, bsize: 0, hash: 'H', issuer: 'I', time: 1, membersCount: 1, issuersCount: 1, issuersFrame: 1, issuersFrameVar: 1, avgBlockSize: 0, medianTime: 1, dividend: 10, mass: 100, unitBase: 0, powMin: 0, udTime: 0, udReevalTime: 0, diffNumber: 1, speed: 1, massReeval: 1 }) - await blockchain.pushBlock({ number: 1, version: 1, bsize: 0, hash: 'H', issuer: 'I', time: 1, membersCount: 1, issuersCount: 1, issuersFrame: 1, issuersFrameVar: 1, avgBlockSize: 0, medianTime: 1, dividend: 10, mass: 100, unitBase: 0, powMin: 0, udTime: 0, udReevalTime: 0, diffNumber: 1, speed: 1, massReeval: 1 }) - await blockchain.pushBlock({ number: 2, version: 1, bsize: 0, hash: 'H', issuer: 'I', time: 1, membersCount: 1, issuersCount: 1, issuersFrame: 1, issuersFrameVar: 1, avgBlockSize: 0, medianTime: 1, dividend: 10, mass: 100, unitBase: 0, powMin: 0, udTime: 0, udReevalTime: 0, diffNumber: 1, speed: 1, massReeval: 1 }) - const HEAD0 = await blockchain.head() - const HEAD1 = await blockchain.head(1) - const HEAD2 = await blockchain.head(2) - const BLOCK0 = await blockchain.getBlock(0) - const BLOCK1 = await blockchain.getBlock(1) - const BLOCK2 = await blockchain.getBlock(2) - assert.equal(HEAD0.number, 2) - assert.equal(HEAD1.number, 1) - assert.equal(HEAD2.number, 0) - assert.deepEqual(HEAD2, BLOCK0) - assert.deepEqual(HEAD1, BLOCK1) - assert.deepEqual(HEAD0, BLOCK2) - }) - - it('should be able to read a range', async () => { - const range1 = await blockchain.headRange(2) - assert.equal(range1.length, 2) - assert.equal(range1[0].number, 2) - assert.equal(range1[1].number, 1) - const range2 = await blockchain.headRange(6) - assert.equal(range2.length, 3) - assert.equal(range2[0].number, 2) - assert.equal(range2[1].number, 1) - assert.equal(range2[2].number, 0) - }) - - it('should have a good height', async () => { - const height1 = await blockchain.height() - await blockchain.pushBlock({ number: 3, version: 1, bsize: 0, hash: 'H', issuer: 'I', time: 1, membersCount: 1, issuersCount: 1, issuersFrame: 1, issuersFrameVar: 1, avgBlockSize: 0, medianTime: 1, dividend: 10, mass: 100, unitBase: 0, powMin: 0, udTime: 0, udReevalTime: 0, diffNumber: 1, speed: 1, massReeval: 1 }) - const height2 = await blockchain.height() - const height3 = await emptyBlockchain.height() - assert.equal(height1, 3) - assert.equal(height2, 4) - assert.equal(height3, 0) - }) - - it('should be able to revert blocks', async () => { - const reverted = await blockchain.revertHead() - const height2 = await blockchain.height() - assert.equal(height2, 3) - assert.equal(reverted.number, 3) - }) - -}) diff --git a/test/blockchain/indexed-blockchain.ts b/test/blockchain/indexed-blockchain.ts deleted file mode 100644 index 8304e1c32e5c05d653980ac21d52d633b550777b..0000000000000000000000000000000000000000 --- a/test/blockchain/indexed-blockchain.ts +++ /dev/null @@ -1,467 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -"use strict"; -import {ArrayBlockchain} from "./lib/ArrayBlockchain" -import {IndexedBlockchain} from "../../app/lib/blockchain/IndexedBlockchain" -import {MemoryIndex} from "./lib/MemoryIndex" -import {SQLIndex} from "../../app/lib/blockchain/SqlIndex" -import {SQLiteDriver} from "../../app/lib/dal/drivers/SQLiteDriver" - -const assert = require('assert') - -describe('Indexed Blockchain', () => { - - describe('MemoryIndex', () => { - - let blockchain:any - - describe('PK on one field', () => { - - before(() => { - blockchain = new IndexedBlockchain(new ArrayBlockchain(), new MemoryIndex(), 'writtenOn', { - iindex: { - pk: 'name', - remove: 'expired' - }, - zindex: { - pk: 'name' - } - }) - }) - - it('should be able to index data', async () => { - await blockchain.recordIndex({ - iindex: [ - { name: 'A', status: 'OK', writtenOn: 23000, events: 0, member: false }, - { name: 'A', status: 'OK', writtenOn: 23000, events: 4 }, - { name: 'A', status: 'OK', writtenOn: 23000, events: 5, member: true }, - { name: 'A', status: 'OK', writtenOn: 23601 }, - { name: 'A', status: 'OK', writtenOn: 23888 }, - { name: 'A', status: 'OK', writtenOn: 23889 }, - { name: 'B', status: 'OK', writtenOn: 23000, events: 1, member: false }, - { name: 'B', status: 'KO', writtenOn: 23000, events: null }, - { name: 'C', status: 'KO', writtenOn: 23500 }, - { name: 'D', status: 'KO', writtenOn: 23500 }, - { name: 'D', status: 'KO', writtenOn: 23521, expired: true } - ] - }) - }) - - it('should be able to reduce data', async () => { - const reducedA = await blockchain.indexReduce('iindex', { name: 'A' }) - const reducedB = await blockchain.indexReduce('iindex', { name: 'B' }) - assert.deepEqual(reducedA, { name: 'A', status: 'OK', writtenOn: 23889, events: 5, member: true }) - assert.deepEqual(reducedB, { name: 'B', status: 'KO', writtenOn: 23000, events: 1, member: false }) - }) - - it('should be able to count data', async () => { - const countAi = await blockchain.indexCount('iindex', { name: 'A' }) - const countBi = await blockchain.indexCount('iindex', { name: 'B' }) - const countCi = await blockchain.indexCount('iindex', { name: 'C' }) - const countDi = await blockchain.indexCount('iindex', { name: 'D' }) - const countBz = await blockchain.indexCount('zindex', { name: 'B' }) - assert.equal(countAi, 6) - assert.equal(countBi, 2) - assert.equal(countCi, 1) - assert.equal(countDi, 2) - assert.equal(countBz, 0) - }) - - it('should be able to reduce grouped data', async () => { - const reducedBy = await blockchain.indexReduceGroupBy('iindex', { writtenOn: 23000 }, ['name']) - assert.deepEqual(reducedBy, [ - { name: 'A', status: 'OK', writtenOn: 23000, events: 5, member: true }, - { name: 'B', status: 'KO', writtenOn: 23000, events: 1, member: false } - ]) - }) - - it('should be able to trim data', async () => { - // The number of records should decrease - await blockchain.indexTrim(23601) - const countAi = await blockchain.indexCount('iindex', { name: 'A' }) - const countBi = await blockchain.indexCount('iindex', { name: 'B' }) - const countCi = await blockchain.indexCount('iindex', { name: 'C' }) - const countDi = await blockchain.indexCount('iindex', { name: 'D' }) - const countBz = await blockchain.indexCount('zindex', { name: 'B' }) - assert.equal(countAi, 4) - assert.equal(countBi, 1) - assert.equal(countCi, 1) - assert.equal(countDi, 0) // Expired = remove rows on trim - assert.equal(countBz, 0) - const reducedAi = await blockchain.indexReduce('iindex', { name: 'A' }) - const reducedBi = await blockchain.indexReduce('iindex', { name: 'B' }) - const reducedCi = await blockchain.indexReduce('iindex', { name: 'C' }) - const reducedDi = await blockchain.indexReduce('iindex', { name: 'D' }) - const reducedBz = await blockchain.indexReduce('zindex', { name: 'B' }) - assert.deepEqual(reducedAi, { name: 'A', status: 'OK', writtenOn: 23889, events: 5, member: true }) - assert.deepEqual(reducedBi, { name: 'B', status: 'KO', writtenOn: 23000, events: 1, member: false }) - assert.deepEqual(reducedCi, { name: 'C', status: 'KO', writtenOn: 23500 }) - assert.deepEqual(reducedDi, {}) - assert.deepEqual(reducedBz, {}) - }) - }) - - describe('PK on two fields', () => { - - before(() => { - blockchain = new IndexedBlockchain(new ArrayBlockchain(), new MemoryIndex(), 'writtenOn', { - iindex: { - pk: ['id', 'pos'], - remove: 'expired' - }, - zindex: { - pk: 'name' - } - }) - }) - - it('should be able to index data', async () => { - await blockchain.recordIndex({ - iindex: [ - { id: 'A', pos: 0, status: 'OK', writtenOn: 23000, events: 0, member: false }, - { id: 'A', pos: 0, status: 'OK', writtenOn: 23000, events: 4 }, - { id: 'A', pos: 0, status: 'OK', writtenOn: 23000, events: 5, member: true }, - { id: 'A', pos: 0, status: 'OK', writtenOn: 23601 }, - { id: 'A', pos: 1, status: 'OK', writtenOn: 23888 }, - { id: 'A', pos: 2, status: 'OK', writtenOn: 23889 }, - { id: 'B', pos: 0, status: 'OK', writtenOn: 23000, events: 1, member: false }, - { id: 'B', pos: 0, status: 'KO', writtenOn: 23000, events: null }, - { id: 'C', pos: 0, status: 'KO', writtenOn: 23500 }, - { id: 'D', pos: 0, status: 'KO', writtenOn: 23500 }, - { id: 'D', pos: 1, status: 'KO', writtenOn: 23521, expired: true } - ] - }) - }) - - it('should be able to reduce data', async () => { - const reducedA = await blockchain.indexReduce('iindex', { id: 'A', pos: 0 }) - const reducedB = await blockchain.indexReduce('iindex', { id: 'B', pos: 0 }) - assert.deepEqual(reducedA, { id: 'A', pos: 0, status: 'OK', writtenOn: 23601, events: 5, member: true }) - assert.deepEqual(reducedB, { id: 'B', pos: 0, status: 'KO', writtenOn: 23000, events: 1, member: false }) - }) - - it('should be able to count data', async () => { - const countAi = await blockchain.indexCount('iindex', { id: 'A', pos: 0 }) - const countBi = await blockchain.indexCount('iindex', { id: 'B', pos: 0 }) - const countCi = await blockchain.indexCount('iindex', { id: 'C', pos: 0 }) - const countDi = await blockchain.indexCount('iindex', { id: 'D', pos: 0 }) - const countBz = await blockchain.indexCount('zindex', { id: 'B', pos: 0 }) - assert.equal(countAi, 4) - assert.equal(countBi, 2) - assert.equal(countCi, 1) - assert.equal(countDi, 1) - assert.equal(countBz, 0) - }) - - it('should be able to reduce grouped data', async () => { - const reducedBy = await blockchain.indexReduceGroupBy('iindex', { writtenOn: 23000 }, ['id', 'pos']) - assert.deepEqual(reducedBy, [ - { id: 'A', pos: 0, status: 'OK', writtenOn: 23000, events: 5, member: true }, - { id: 'B', pos: 0, status: 'KO', writtenOn: 23000, events: 1, member: false } - ]) - }) - - it('should be able to trim data', async () => { - // The number of records should decrease - await blockchain.indexTrim(23601) - const countAi = await blockchain.indexCount('iindex', { id: 'A', pos: 0 }) - const countBi = await blockchain.indexCount('iindex', { id: 'B', pos: 0 }) - const countCi = await blockchain.indexCount('iindex', { id: 'C', pos: 0 }) - const countDi = await blockchain.indexCount('iindex', { id: 'D', pos: 0 }) - const countBz = await blockchain.indexCount('zindex', { id: 'B', pos: 0 }) - assert.equal(countAi, 2) - assert.equal(countBi, 1) - assert.equal(countCi, 1) - assert.equal(countDi, 1) // Not expired! - assert.equal(countBz, 0) - const reducedAi = await blockchain.indexReduce('iindex', { id: 'A', pos: 0 }) - const reducedBi = await blockchain.indexReduce('iindex', { id: 'B', pos: 0 }) - const reducedCi = await blockchain.indexReduce('iindex', { id: 'C', pos: 0 }) - const reducedDi = await blockchain.indexReduce('iindex', { id: 'D', pos: 0 }) - const reducedBz = await blockchain.indexReduce('zindex', { id: 'B', pos: 0 }) - assert.deepEqual(reducedAi, { id: 'A', pos: 0, status: 'OK', writtenOn: 23601, events: 5, member: true }) - assert.deepEqual(reducedBi, { id: 'B', pos: 0, status: 'KO', writtenOn: 23000, events: 1, member: false }) - assert.deepEqual(reducedCi, { id: 'C', pos: 0, status: 'KO', writtenOn: 23500 }) - assert.deepEqual(reducedDi, { id: 'D', pos: 0, status: 'KO', writtenOn: 23500 }) - assert.deepEqual(reducedBz, {}) - }) - }) - }) - - describe('SqlIndex', () => { - - let blockchain:any - - describe('PK on one field', () => { - - before(() => { - const db = new SQLiteDriver(':memory:') - blockchain = new IndexedBlockchain(new ArrayBlockchain(), new SQLIndex(db, { - iindex: { - sqlFields: [ - 'name CHAR(1) NULL', - 'status CHAR(2) NULL', - 'writtenOn INTEGER NULL', - 'events INTEGER NULL', - 'member INTEGER NULL', - 'expired INTEGER NULL' - ], - fields: [ - 'name', - 'status', - 'writtenOn', - 'events', - 'member', - 'expired' - ], - booleans: ['member', 'expired'] - }, - zindex: { - sqlFields: [ - 'name CHAR(1) NULL', - 'status CHAR(2) NULL', - 'writtenOn INTEGER NULL', - 'events INTEGER NULL', - 'member INTEGER NULL', - 'expired INTEGER NULL' - ], - fields: [ - 'name', - 'status', - 'writtenOn', - 'events', - 'member', - 'expired' - ], - booleans: ['member', 'expired'] - } - }), 'writtenOn', { - iindex: { - pk: 'name', - remove: 'expired' - }, - zindex: { - pk: 'name' - } - }) - }) - - it('should be able to index data', async () => { - await blockchain.recordIndex({ - iindex: [ - { name: 'A', status: 'OK', writtenOn: 23000, events: 0, member: false }, - { name: 'A', status: 'OK', writtenOn: 23000, events: 4 }, - { name: 'A', status: 'OK', writtenOn: 23000, events: 5, member: true }, - { name: 'A', status: 'OK', writtenOn: 23601 }, - { name: 'A', status: 'OK', writtenOn: 23888 }, - { name: 'A', status: 'OK', writtenOn: 23889 }, - { name: 'B', status: 'OK', writtenOn: 23000, events: 1, member: false }, - { name: 'B', status: 'KO', writtenOn: 23000, events: null }, - { name: 'C', status: 'KO', writtenOn: 23500 }, - { name: 'D', status: 'KO', writtenOn: 23500 }, - { name: 'D', status: 'KO', writtenOn: 23521, expired: true } - ] - }) - }) - - it('should be able to reduce data', async () => { - const reducedA = await blockchain.indexReduce('iindex', { name: 'A' }) - const reducedB = await blockchain.indexReduce('iindex', { name: 'B' }) - assert.deepEqual(reducedA, { name: 'A', status: 'OK', writtenOn: 23889, events: 5, member: true }) - assert.deepEqual(reducedB, { name: 'B', status: 'KO', writtenOn: 23000, events: 1, member: false }) - }) - - it('should be able to count data', async () => { - const countAi = await blockchain.indexCount('iindex', { name: 'A' }) - const countBi = await blockchain.indexCount('iindex', { name: 'B' }) - const countCi = await blockchain.indexCount('iindex', { name: 'C' }) - const countDi = await blockchain.indexCount('iindex', { name: 'D' }) - const countBz = await blockchain.indexCount('zindex', { name: 'B' }) - assert.equal(countAi, 6) - assert.equal(countBi, 2) - assert.equal(countCi, 1) - assert.equal(countDi, 2) - assert.equal(countBz, 0) - }) - - it('should be able to reduce grouped data', async () => { - const reducedBy = await blockchain.indexReduceGroupBy('iindex', { writtenOn: 23000 }, ['name']) - assert.deepEqual(reducedBy, [ - { name: 'A', status: 'OK', writtenOn: 23000, events: 5, member: true }, - { name: 'B', status: 'KO', writtenOn: 23000, events: 1, member: false } - ]) - }) - - it('should be able to trim data', async () => { - // The number of records should decrease - await blockchain.indexTrim(23601) - const countAi = await blockchain.indexCount('iindex', { name: 'A' }) - const countBi = await blockchain.indexCount('iindex', { name: 'B' }) - const countCi = await blockchain.indexCount('iindex', { name: 'C' }) - const countDi = await blockchain.indexCount('iindex', { name: 'D' }) - const countBz = await blockchain.indexCount('zindex', { name: 'B' }) - assert.equal(countAi, 4) - assert.equal(countBi, 1) - assert.equal(countCi, 1) - assert.equal(countDi, 0) // Expired = remove rows on trim - assert.equal(countBz, 0) - const reducedAi = await blockchain.indexReduce('iindex', { name: 'A' }) - const reducedBi = await blockchain.indexReduce('iindex', { name: 'B' }) - const reducedCi = await blockchain.indexReduce('iindex', { name: 'C' }) - const reducedDi = await blockchain.indexReduce('iindex', { name: 'D' }) - const reducedBz = await blockchain.indexReduce('zindex', { name: 'B' }) - assert.deepEqual(reducedAi, { name: 'A', status: 'OK', writtenOn: 23889, events: 5, member: true }) - assert.deepEqual(reducedBi, { name: 'B', status: 'KO', writtenOn: 23000, events: 1, member: false }) - assert.deepEqual(reducedCi, { name: 'C', status: 'KO', writtenOn: 23500 }) - assert.deepEqual(reducedDi, {}) - assert.deepEqual(reducedBz, {}) - }) - }) - - describe('PK on two fields', () => { - - before(() => { - const db = new SQLiteDriver(':memory:') - blockchain = new IndexedBlockchain(new ArrayBlockchain(), new SQLIndex(db, { - iindex: { - sqlFields: [ - 'id INTEGER NULL', - 'pos INTEGER NULL', - 'name CHAR(1) NULL', - 'status CHAR(2) NULL', - 'writtenOn INTEGER NULL', - 'events INTEGER NULL', - 'member INTEGER NULL', - 'expired INTEGER NULL' - ], - fields: [ - 'id', - 'pos', - 'name', - 'status', - 'writtenOn', - 'events', - 'member', - 'expired' - ], - booleans: ['member', 'expired'] - }, - zindex: { - sqlFields: [ - 'id INTEGER NULL', - 'pos INTEGER NULL', - 'name CHAR(1) NULL', - 'status CHAR(2) NULL', - 'writtenOn INTEGER NULL', - 'events INTEGER NULL', - 'member INTEGER NULL', - 'expired INTEGER NULL' - ], - fields: [ - 'id', - 'pos', - 'name', - 'status', - 'writtenOn', - 'events', - 'member', - 'expired' - ], - booleans: ['member', 'expired'] - } - }), 'writtenOn', { - iindex: { - pk: ['id', 'pos'], - remove: 'expired' - }, - zindex: { - pk: 'name' - } - }) - }) - - it('should be able to index data', async () => { - await blockchain.recordIndex({ - iindex: [ - { id: 'A', pos: 0, status: 'OK', writtenOn: 23000, events: 0, member: false }, - { id: 'A', pos: 0, status: 'OK', writtenOn: 23000, events: 4 }, - { id: 'A', pos: 0, status: 'OK', writtenOn: 23000, events: 5, member: true }, - { id: 'A', pos: 0, status: 'OK', writtenOn: 23601 }, - { id: 'A', pos: 1, status: 'OK', writtenOn: 23888 }, - { id: 'A', pos: 2, status: 'OK', writtenOn: 23889 }, - { id: 'B', pos: 0, status: 'OK', writtenOn: 23000, events: 1, member: false }, - { id: 'B', pos: 0, status: 'KO', writtenOn: 23000, events: null }, - { id: 'C', pos: 0, status: 'KO', writtenOn: 23500 }, - { id: 'D', pos: 0, status: 'KO', writtenOn: 23500 }, - { id: 'D', pos: 1, status: 'KO', writtenOn: 23521, expired: true } - ] - }) - }) - - it('should be able to reduce data', async () => { - const reducedA = await blockchain.indexReduce('iindex', { id: 'A', pos: 0 }) - const reducedB = await blockchain.indexReduce('iindex', { id: 'B', pos: 0 }) - assert.deepEqual(reducedA, { id: 'A', pos: 0, status: 'OK', writtenOn: 23601, events: 5, member: true }) - assert.deepEqual(reducedB, { id: 'B', pos: 0, status: 'KO', writtenOn: 23000, events: 1, member: false }) - }) - - it('should be able to count data', async () => { - const countAi = await blockchain.indexCount('iindex', { id: 'A', pos: 0 }) - const countBi = await blockchain.indexCount('iindex', { id: 'B', pos: 0 }) - const countCi = await blockchain.indexCount('iindex', { id: 'C', pos: 0 }) - const countDi = await blockchain.indexCount('iindex', { id: 'D', pos: 0 }) - const countBz = await blockchain.indexCount('zindex', { id: 'B', pos: 0 }) - assert.equal(countAi, 4) - assert.equal(countBi, 2) - assert.equal(countCi, 1) - assert.equal(countDi, 1) - assert.equal(countBz, 0) - }) - - it('should be able to reduce grouped data', async () => { - const reducedBy = await blockchain.indexReduceGroupBy('iindex', { writtenOn: 23000 }, ['id', 'pos']) - assert.deepEqual(reducedBy, [ - { id: 'A', pos: 0, status: 'OK', writtenOn: 23000, events: 5, member: true }, - { id: 'B', pos: 0, status: 'KO', writtenOn: 23000, events: 1, member: false } - ]) - }) - - it('should be able to trim data', async () => { - // The number of records should decrease - await blockchain.indexTrim(23601) - const countAi = await blockchain.indexCount('iindex', { id: 'A', pos: 0 }) - const countBi = await blockchain.indexCount('iindex', { id: 'B', pos: 0 }) - const countCi = await blockchain.indexCount('iindex', { id: 'C', pos: 0 }) - const countDi = await blockchain.indexCount('iindex', { id: 'D', pos: 0 }) - const countBz = await blockchain.indexCount('zindex', { id: 'B', pos: 0 }) - assert.equal(countAi, 2) - assert.equal(countBi, 1) - assert.equal(countCi, 1) - assert.equal(countDi, 1) // Not expired! - assert.equal(countBz, 0) - const reducedAi = await blockchain.indexReduce('iindex', { id: 'A', pos: 0 }) - const reducedBi = await blockchain.indexReduce('iindex', { id: 'B', pos: 0 }) - const reducedCi = await blockchain.indexReduce('iindex', { id: 'C', pos: 0 }) - const reducedDi = await blockchain.indexReduce('iindex', { id: 'D', pos: 0 }) - const reducedBz = await blockchain.indexReduce('zindex', { id: 'B', pos: 0 }) - assert.deepEqual(reducedAi, { id: 'A', pos: 0, status: 'OK', writtenOn: 23601, events: 5, member: true }) - assert.deepEqual(reducedBi, { id: 'B', pos: 0, status: 'KO', writtenOn: 23000, events: 1, member: false }) - assert.deepEqual(reducedCi, { id: 'C', pos: 0, status: 'KO', writtenOn: 23500 }) - assert.deepEqual(reducedDi, { id: 'D', pos: 0, status: 'KO', writtenOn: 23500 }) - assert.deepEqual(reducedBz, {}) - }) - }) - }) - -}) diff --git a/test/blockchain/lib/ArrayBlockchain.ts b/test/blockchain/lib/ArrayBlockchain.ts deleted file mode 100644 index 25c0fc576e48d3ee7c7e8dde2d64e6bcf895defd..0000000000000000000000000000000000000000 --- a/test/blockchain/lib/ArrayBlockchain.ts +++ /dev/null @@ -1,48 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -import {BlockchainOperator} from "../../../app/lib/blockchain/interfaces/BlockchainOperator" - -export class ArrayBlockchain implements BlockchainOperator { - - // The blockchain storage - private bcArray: any[] = [] - - store(b:any): Promise<any> { - this.bcArray.push(b) - return Promise.resolve(b) - } - - read(i: number): Promise<any> { - return Promise.resolve(this.bcArray[i]) - } - - head(n: number): Promise<any> { - const index = Math.max(0, this.bcArray.length - 1 - (n || 0)) - return Promise.resolve(this.bcArray[index]) - } - - height(): Promise<number> { - return Promise.resolve(this.bcArray.length) - } - - headRange(m: number): Promise<any[]> { - const index = Math.max(0, this.bcArray.length - (m || 0)) - return Promise.resolve(this.bcArray.slice(index, this.bcArray.length).reverse()) - } - - revertHead(): Promise<any> { - const reverted = this.bcArray.pop() - return Promise.resolve(reverted) - } -} diff --git a/test/blockchain/lib/MemoryIndex.ts b/test/blockchain/lib/MemoryIndex.ts deleted file mode 100644 index cfd6471f43c67253554388223971f3c08d1b081f..0000000000000000000000000000000000000000 --- a/test/blockchain/lib/MemoryIndex.ts +++ /dev/null @@ -1,108 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -"use strict" -import {IndexOperator} from "../../../app/lib/blockchain/interfaces/IndexOperator" - -const _ = require('underscore') - -export class MemoryIndex implements IndexOperator { - - // The blockchain storage - private indexStorage: { [index: string]: any[] } = { } - - initIndexer(pkFields: any): Promise<void> { - return Promise.resolve() - } - - getSubIndexes(): Promise<string[]> { - return Promise.resolve(_.keys(this.indexStorage)) - } - - findTrimable(subIndex: string, numberField: string, maxNumber: number): Promise<any[]> { - const criterias:any = {} - criterias[numberField] = { $lt: maxNumber } - return this.findWhere(subIndex, criterias) - } - - removeWhere(subIndex: string, criterias: {}): Promise<void> { - let i = 0 - let rows = this.indexStorage[subIndex] - while (i < rows.length) { - if (MemoryIndex.matchComplexCriterias(criterias, rows[i])) { - rows.splice(i, 1) - } else { - i++ - } - } - return Promise.resolve() - } - - recordIndex(index: any): Promise<void> { - const subIndexes = _.keys(index) - // Create subIndexes if they do not exist - for (const subIndex of subIndexes) { - this.indexStorage[subIndex] = this.indexStorage[subIndex] || [] - } - // Feed the subIndexes - for (const subIndex of subIndexes) { - this.indexStorage[subIndex] = this.indexStorage[subIndex].concat(index[subIndex]) - } - return Promise.resolve() - } - - private static matchComplexCriterias(criterias:any, row:any): boolean { - const criteriaKeys = _.keys(criterias) - let matches = true - let i = 0 - while (matches && i < criteriaKeys.length) { - const k = criteriaKeys[i] - if (typeof criterias[k] === 'function') { - matches = criterias[k](row[k]) - } else if (typeof criterias[k] === 'object') { - if (criterias[k].$lt) { - matches = row[k] < criterias[k].$lt - } else if (criterias[k].$gt) { - matches = row[k] > criterias[k].$gt - } else if (criterias[k].$lte) { - matches = row[k] <= criterias[k].$lte - } else if (criterias[k].$gte) { - matches = row[k] >= criterias[k].$gte - } else { - // Unknown predicate - matches = false - } - } else { - matches = row[k] === criterias[k] - } - i++ - } - return matches - } - - findWhere(subIndex: string, criterias: {}): Promise<any[]> { - let res: any[] = [] - const areBasicCriterias = _.values(criterias).reduce((are:boolean, criteria:any) => are && typeof criteria !== 'function' && typeof criteria !== 'object', true) - if (areBasicCriterias) { - res = _.where(this.indexStorage[subIndex], criterias) - } else { - // Slower test, with specific criterias - for (const row of this.indexStorage[subIndex]) { - if (MemoryIndex.matchComplexCriterias(criterias, row)) { - res.push(row) - } - } - } - return Promise.resolve(res) - } -} diff --git a/test/blockchain/misc-sql-blockchain.ts b/test/blockchain/misc-sql-blockchain.ts deleted file mode 100644 index 8e41ae1f66b18f982ad82d6a9b7fa94f950ea030..0000000000000000000000000000000000000000 --- a/test/blockchain/misc-sql-blockchain.ts +++ /dev/null @@ -1,233 +0,0 @@ -// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1 -// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -"use strict"; -import {MiscIndexedBlockchain} from "../../app/lib/blockchain/MiscIndexedBlockchain" -import {ArrayBlockchain} from "./lib/ArrayBlockchain" -import {SQLiteDriver} from "../../app/lib/dal/drivers/SQLiteDriver" -import {MIndexDAL} from "../../app/lib/dal/sqliteDAL/index/MIndexDAL"; -import {IIndexDAL} from "../../app/lib/dal/sqliteDAL/index/IIndexDAL"; -import {SIndexDAL} from "../../app/lib/dal/sqliteDAL/index/SIndexDAL"; -import {CIndexDAL} from "../../app/lib/dal/sqliteDAL/index/CIndexDAL"; -import {MetaDAL} from "../../app/lib/dal/sqliteDAL/MetaDAL"; -import {ConfDTO} from "../../app/lib/dto/ConfDTO"; - -const assert = require('assert') - -describe.skip('MISC SQL Blockchain', () => { - - let blockchain:any - - before(async () => { - - const db = new SQLiteDriver(':memory:') - - const mindexDAL = new MIndexDAL(db) - const iindexDAL = new IIndexDAL(db) - const sindexDAL = new SIndexDAL(db) - const cindexDAL = new CIndexDAL(db) - const metaDAL = new MetaDAL(db) - - await iindexDAL.init() - await mindexDAL.init() - await sindexDAL.init() - await cindexDAL.init() - await metaDAL.init() - // Ghost tables required for DB upgrade - await metaDAL.exec('CREATE TABLE txs (id INTEGER null);') - await metaDAL.exec('CREATE TABLE idty (id INTEGER null);') - await metaDAL.exec('CREATE TABLE cert (id INTEGER null);') - await metaDAL.exec('CREATE TABLE membership (id INTEGER null);') - await metaDAL.exec('CREATE TABLE block (fork INTEGER null);') - await metaDAL.exec('CREATE TABLE b_index (id INTEGER null);') - await metaDAL.upgradeDatabase(ConfDTO.mock()); - - blockchain = new MiscIndexedBlockchain(new ArrayBlockchain(), mindexDAL, iindexDAL, sindexDAL, cindexDAL) - }) - - describe('MINDEX', () => { - - it('should be able to index data', async () => { - await blockchain.recordIndex({ - m_index: [ - { op: 'CREATE', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', writtenOn: 0, expires_on: 1520544727, expired_on: null, revokes_on: 1552102327, revoked_on: null, leaving: false, revocation: null, chainable_on: null }, - { op: 'UPDATE', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '3-0000611A1018A322624853A8AE10D0EBFF3C6AEE37BF4DE5354C720049C22BD1', writtenOn: 3, expires_on: 1520544728, expired_on: null, revokes_on: 1520544728, revoked_on: null, leaving: false, revocation: null, chainable_on: null }, - { op: 'UPDATE', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '4-0000090B7059E7BF5DD2CCA5E4F0330C1DA42C5DCBD2D1364B99B3FF89DE6744', writtenOn: 4, expires_on: 1520544729, expired_on: null, revokes_on: 1520544729, revoked_on: null, leaving: false, revocation: null, chainable_on: null } - ] - }) - }) - - it('should be able to reduce data', async () => { - const reducedG5 = await blockchain.indexReduce('m_index', { pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT' }) - assert.deepEqual(reducedG5, { op: 'UPDATE', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '4-0000090B7059E7BF5DD2CCA5E4F0330C1DA42C5DCBD2D1364B99B3FF89DE6744', writtenOn: 4, expires_on: 1520544729, revokes_on: 1520544729, leaving: false }) - }) - - it('should be able to count data', async () => { - const countG5 = await blockchain.indexCount('m_index', { pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT' }) - assert.equal(countG5, 3) - }) - - it('should be able to reduce grouped data', async () => { - const reducedBy = await blockchain.indexReduceGroupBy('m_index', { created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855' }, ['op', 'pub']) - assert.deepEqual(reducedBy, [ - { op: 'CREATE', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', writtenOn: 0, expires_on: 1520544727, revokes_on: 1552102327, leaving: false }, - { op: 'UPDATE', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '4-0000090B7059E7BF5DD2CCA5E4F0330C1DA42C5DCBD2D1364B99B3FF89DE6744', writtenOn: 4, expires_on: 1520544729, revokes_on: 1520544729, leaving: false } - ]) - }) - - it('should be able to trim data', async () => { - // The number of records should decrease - await blockchain.indexTrim(4) - const countG5 = await blockchain.indexCount('m_index', { pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT' }) - assert.equal(countG5, 2) - const reducedG5 = await blockchain.indexReduce('m_index', { pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT' }) - assert.deepEqual(reducedG5, { op: 'UPDATE', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '4-0000090B7059E7BF5DD2CCA5E4F0330C1DA42C5DCBD2D1364B99B3FF89DE6744', writtenOn: 4, expires_on: 1520544729, revokes_on: 1520544729, leaving: false }) - }) - }) - - describe('IINDEX', () => { - - it('should be able to index data', async () => { - await blockchain.recordIndex({ - i_index: [ - { op: 'CREATE', uid: 'pseudo', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', hash: '1505A45A5EEBFC3AFAD1475A4739C8447A79420A83340559CE5A49F9891167BB', sig: '2vfmih7xhW/QLJ85PZH1Tc6j5fooIXca+yr/esnt0yvdk5LhEKrOB32JFqCctAoRNwpRjBdZ2Q8l15+In1rrDg==', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', writtenOn: 0, member: true, wasMember: true, kick: false, wotb_id: 164 }, - { op: 'UPDATE', uid: 'pseudo', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', hash: '1505A45A5EEBFC3AFAD1475A4739C8447A79420A83340559CE5A49F9891167BB', sig: '2vfmih7xhW/QLJ85PZH1Tc6j5fooIXca+yr/esnt0yvdk5LhEKrOB32JFqCctAoRNwpRjBdZ2Q8l15+In1rrDg==', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '33396-000009C936CD6F7C5672C1E6D36159E0BEA2B394F386CA0EBA7E73662A09BB43', writtenOn: 33396, member: false, wasMember: true, kick: false, wotb_id: 164 }, - { op: 'UPDATE', uid: 'pseudo', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', hash: '1505A45A5EEBFC3AFAD1475A4739C8447A79420A83340559CE5A49F9891167BB', sig: '2vfmih7xhW/QLJ85PZH1Tc6j5fooIXca+yr/esnt0yvdk5LhEKrOB32JFqCctAoRNwpRjBdZ2Q8l15+In1rrDg==', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '40000-000006C311D2677D101116287718395A2CBB7B94389004D19B0E4AC6DCE2DE5F', writtenOn: 40000, member: true, wasMember: true, kick: false, wotb_id: 164 } - ] - }) - }) - - it('should be able to reduce data', async () => { - const reducedG5 = await blockchain.indexReduce('i_index', { pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT' }) - assert.deepEqual(reducedG5, { op: 'UPDATE', uid: 'pseudo', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', hash: '1505A45A5EEBFC3AFAD1475A4739C8447A79420A83340559CE5A49F9891167BB', sig: '2vfmih7xhW/QLJ85PZH1Tc6j5fooIXca+yr/esnt0yvdk5LhEKrOB32JFqCctAoRNwpRjBdZ2Q8l15+In1rrDg==', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '40000-000006C311D2677D101116287718395A2CBB7B94389004D19B0E4AC6DCE2DE5F', writtenOn: 40000, member: true, wasMember: true, kick: false, wotb_id: 164 }) - }) - - it('should be able to count data', async () => { - const countG5 = await blockchain.indexCount('i_index', { pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT' }) - assert.equal(countG5, 3) - }) - - it('should be able to reduce grouped data', async () => { - const reducedBy = await blockchain.indexReduceGroupBy('i_index', { created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855' }, ['op', 'pub']) - assert.deepEqual(reducedBy, [ - { op: 'CREATE', uid: 'pseudo', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', hash: '1505A45A5EEBFC3AFAD1475A4739C8447A79420A83340559CE5A49F9891167BB', sig: '2vfmih7xhW/QLJ85PZH1Tc6j5fooIXca+yr/esnt0yvdk5LhEKrOB32JFqCctAoRNwpRjBdZ2Q8l15+In1rrDg==', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', writtenOn: 0, member: true, wasMember: true, kick: false, wotb_id: 164 }, - { op: 'UPDATE', uid: 'pseudo', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', hash: '1505A45A5EEBFC3AFAD1475A4739C8447A79420A83340559CE5A49F9891167BB', sig: '2vfmih7xhW/QLJ85PZH1Tc6j5fooIXca+yr/esnt0yvdk5LhEKrOB32JFqCctAoRNwpRjBdZ2Q8l15+In1rrDg==', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '40000-000006C311D2677D101116287718395A2CBB7B94389004D19B0E4AC6DCE2DE5F', writtenOn: 40000, member: true, wasMember: true, kick: false, wotb_id: 164 } - ]) - }) - - it('should be able to trim data', async () => { - // The number of records should decrease - await blockchain.indexTrim(40000) - const countG5 = await blockchain.indexCount('i_index', { pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT' }) - assert.equal(countG5, 2) - const reducedG5 = await blockchain.indexReduce('i_index', { pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT' }) - assert.deepEqual(reducedG5, { op: 'UPDATE', uid: 'pseudo', pub: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', hash: '1505A45A5EEBFC3AFAD1475A4739C8447A79420A83340559CE5A49F9891167BB', sig: '2vfmih7xhW/QLJ85PZH1Tc6j5fooIXca+yr/esnt0yvdk5LhEKrOB32JFqCctAoRNwpRjBdZ2Q8l15+In1rrDg==', created_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', written_on: '40000-000006C311D2677D101116287718395A2CBB7B94389004D19B0E4AC6DCE2DE5F', writtenOn: 40000, member: true, wasMember: true, kick: false, wotb_id: 164 }) - }) - }) - - describe('SINDEX', () => { - - it('should be able to index data', async () => { - await blockchain.recordIndex({ - s_index: [ - // Dividend - { op: 'CREATE', tx: null, identifier: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', pos: 35820, created_on: null, written_on: '35820-00000B363BC8F761EB5343660592D50B872FE1140B350C9780EF5BC6F9DD000B', writtenOn: 35820, written_time: 1500000000, amount: 500, base: 0, locktime: 0, consumed: false, conditions: 'SIG(CPEaW4BGNaBdx6FbAxjNQ9Po2apnX2bDvBXJT9yaZUMc)' }, - { op: 'UPDATE', tx: null, identifier: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', pos: 35820, created_on: null, written_on: '35821-0000053C7B54AEFAEC4FCFB2763202ECD8382A635340BD622EDBC0CCC553F763', writtenOn: 35821, written_time: 1500000001, amount: 500, base: 0, locktime: 0, consumed: true, conditions: 'SIG(CPEaW4BGNaBdx6FbAxjNQ9Po2apnX2bDvBXJT9yaZUMc)' }, - // Transaction - { op: 'CREATE', tx: 'D01432C6D7D078CB566C08886FD92CA5D158433D7A8D971124973625BFAB78D9', identifier: 'D01432C6D7D078CB566C08886FD92CA5D158433D7A8D971124973625BFAB78D9', pos: 1, created_on: '33958-0000009CEC38916882EF46C40069EF227F1D7CB4B34EAD5298D84B6658FBB9FB', written_on: '30196-00000A8ABF13284452CD56C9DEC68124D4A31CE1BDD06819EB22E070EBDE1D2D', writtenOn: 30196, written_time: 1499000000, amount: 301, base: 0, locktime: 0, consumed: false, conditions: 'SIG(CPEaW4BGNaBdx6FbAxjNQ9Po2apnX2bDvBXJT9yaZUMc)' }, - { op: 'UPDATE', tx: '3926D234037264654D9C4A2D44CDDC18998DC48262F3677F23DA5BA81BD530EA', identifier: 'D01432C6D7D078CB566C08886FD92CA5D158433D7A8D971124973625BFAB78D9', pos: 1, created_on: '33958-0000009CEC38916882EF46C40069EF227F1D7CB4B34EAD5298D84B6658FBB9FB', written_on: '30197-0000009CEC38916882EF46C40069EF227F1D7CB4B34EAD5298D84B6658FBB9FB', writtenOn: 30197, written_time: 1499000001, amount: 301, base: 0, locktime: 0, consumed: true, conditions: 'SIG(CPEaW4BGNaBdx6FbAxjNQ9Po2apnX2bDvBXJT9yaZUMc)' } - ] - }) - }) - - it('should be able to reduce data', async () => { - const reducedUD = await blockchain.indexReduce('s_index', { identifier: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', pos: 35820 }) - const reducedTX = await blockchain.indexReduce('s_index', { identifier: 'D01432C6D7D078CB566C08886FD92CA5D158433D7A8D971124973625BFAB78D9', pos: 1 }) - assert.deepEqual(reducedUD, { op: 'UPDATE', identifier: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', pos: 35820, written_on: '35821-0000053C7B54AEFAEC4FCFB2763202ECD8382A635340BD622EDBC0CCC553F763', writtenOn: 35821, written_time: 1500000001, amount: 500, base: 0, locktime: 0, consumed: true, conditions: 'SIG(CPEaW4BGNaBdx6FbAxjNQ9Po2apnX2bDvBXJT9yaZUMc)' }) - assert.deepEqual(reducedTX, { op: 'UPDATE', tx: '3926D234037264654D9C4A2D44CDDC18998DC48262F3677F23DA5BA81BD530EA', identifier: 'D01432C6D7D078CB566C08886FD92CA5D158433D7A8D971124973625BFAB78D9', pos: 1, created_on: '33958-0000009CEC38916882EF46C40069EF227F1D7CB4B34EAD5298D84B6658FBB9FB', written_on: '30197-0000009CEC38916882EF46C40069EF227F1D7CB4B34EAD5298D84B6658FBB9FB', writtenOn: 30197, written_time: 1499000001, amount: 301, base: 0, locktime: 0, consumed: true, conditions: 'SIG(CPEaW4BGNaBdx6FbAxjNQ9Po2apnX2bDvBXJT9yaZUMc)' }) - }) - - it('should be able to count data', async () => { - const countUD = await blockchain.indexCount('s_index', { identifier: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', pos: 35820 }) - const countTX = await blockchain.indexCount('s_index', { identifier: 'D01432C6D7D078CB566C08886FD92CA5D158433D7A8D971124973625BFAB78D9', pos: 1 }) - assert.equal(countUD, 2) - assert.equal(countTX, 2) - }) - - it('should be able to reduce grouped data', async () => { - const reducedBy = await blockchain.indexReduceGroupBy('s_index', { pos: { $gt: 0 } }, ['identifier', 'pos']) - assert.deepEqual(reducedBy, [ - { op: 'UPDATE', tx: '3926D234037264654D9C4A2D44CDDC18998DC48262F3677F23DA5BA81BD530EA', identifier: 'D01432C6D7D078CB566C08886FD92CA5D158433D7A8D971124973625BFAB78D9', pos: 1, created_on: '33958-0000009CEC38916882EF46C40069EF227F1D7CB4B34EAD5298D84B6658FBB9FB', written_on: '30197-0000009CEC38916882EF46C40069EF227F1D7CB4B34EAD5298D84B6658FBB9FB', writtenOn: 30197, written_time: 1499000001, amount: 301, base: 0, locktime: 0, consumed: true, conditions: 'SIG(CPEaW4BGNaBdx6FbAxjNQ9Po2apnX2bDvBXJT9yaZUMc)' }, - { op: 'UPDATE', identifier: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', pos: 35820, written_on: '35821-0000053C7B54AEFAEC4FCFB2763202ECD8382A635340BD622EDBC0CCC553F763', writtenOn: 35821, written_time: 1500000001, amount: 500, base: 0, locktime: 0, consumed: true, conditions: 'SIG(CPEaW4BGNaBdx6FbAxjNQ9Po2apnX2bDvBXJT9yaZUMc)' } - ]) - }) - - it('should be able to trim data', async () => { - // The number of records should decrease - await blockchain.indexTrim(35000) - const countUD = await blockchain.indexCount('s_index', { identifier: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', pos: 35820 }) - const countTX = await blockchain.indexCount('s_index', { identifier: 'D01432C6D7D078CB566C08886FD92CA5D158433D7A8D971124973625BFAB78D9', pos: 1 }) - assert.equal(countUD, 2) - assert.equal(countTX, 0) // This index removes the lines marked `consumed` - const reducedUD = await blockchain.indexReduce('s_index', { identifier: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', pos: 35820 }) - assert.deepEqual(reducedUD, { op: 'UPDATE', identifier: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', pos: 35820, written_on: '35821-0000053C7B54AEFAEC4FCFB2763202ECD8382A635340BD622EDBC0CCC553F763', writtenOn: 35821, written_time: 1500000001, amount: 500, base: 0, locktime: 0, consumed: true, conditions: 'SIG(CPEaW4BGNaBdx6FbAxjNQ9Po2apnX2bDvBXJT9yaZUMc)' }) - }) - }) - - describe('CINDEX', () => { - - it('should be able to index data', async () => { - await blockchain.recordIndex({ - c_index: [ - { op: 'CREATE', issuer: 'D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 0, written_on: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', writtenOn: 0, sig: 'MYWlBd2Hw3T/59BDz9HZECBuZ984C23F5lqUGluIUXsvXjsY4xKNqcN2x75s9rn++u4GEzZov6OznLZiHtbAAQ==', expires_on: 1552102327, expired_on: 0, chainable_on: 1489419127 }, - { op: 'UPDATE', issuer: 'D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 0, written_on: '9-0000092C94D0257C61A2504092440600487B2C8BEE73F9C8763C9F351543887D', writtenOn: 9, sig: 'MYWlBd2Hw3T/59BDz9HZECBuZ984C23F5lqUGluIUXsvXjsY4xKNqcN2x75s9rn++u4GEzZov6OznLZiHtbAAQ==', expires_on: 1552102327, expired_on: 1552102400, chainable_on: 1489419127 }, - { op: 'CREATE', issuer: 'EV4yZXAgmDd9rMsRCSH2MK7RHWty7CDB9tmHku3iRnEB', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 11, written_on: '11-000019EC1161FC9FB1848A58A3137B9CD9A919E86B2394B9682BBC3FADB1AF1F', writtenOn: 11, sig: 'plFuA1vgXJh0CQ9MVCmOgfTfFb5u3qICMfgxVJEsyco+lmZTxaKuruSsRdhw3YZgJgfU6YwC+ta/RcgLF6DvDA==', expires_on: 1556866334, expired_on: 0, chainable_on: 1494184082} - ] - }) - }) - - it('should be able to reduce data', async () => { - const reducedC1 = await blockchain.indexReduce('c_index', { issuer: 'D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 0 }) - const reducedC2 = await blockchain.indexReduce('c_index', { issuer: 'EV4yZXAgmDd9rMsRCSH2MK7RHWty7CDB9tmHku3iRnEB', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 11 }) - assert.deepEqual(reducedC1, { op: 'UPDATE', issuer: 'D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 0, written_on: '9-0000092C94D0257C61A2504092440600487B2C8BEE73F9C8763C9F351543887D', writtenOn: 9, sig: 'MYWlBd2Hw3T/59BDz9HZECBuZ984C23F5lqUGluIUXsvXjsY4xKNqcN2x75s9rn++u4GEzZov6OznLZiHtbAAQ==', expires_on: 1552102327, expired_on: 1552102400, chainable_on: 1489419127 }) - assert.deepEqual(reducedC2, { op: 'CREATE', issuer: 'EV4yZXAgmDd9rMsRCSH2MK7RHWty7CDB9tmHku3iRnEB', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 11, written_on: '11-000019EC1161FC9FB1848A58A3137B9CD9A919E86B2394B9682BBC3FADB1AF1F', writtenOn: 11, sig: 'plFuA1vgXJh0CQ9MVCmOgfTfFb5u3qICMfgxVJEsyco+lmZTxaKuruSsRdhw3YZgJgfU6YwC+ta/RcgLF6DvDA==', expires_on: 1556866334, expired_on: 0, chainable_on: 1494184082}) - }) - - it('should be able to count data', async () => { - const countC1 = await blockchain.indexCount('c_index', { issuer: 'D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 0 }) - const countC2 = await blockchain.indexCount('c_index', { issuer: 'EV4yZXAgmDd9rMsRCSH2MK7RHWty7CDB9tmHku3iRnEB', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 11 }) - assert.equal(countC1, 2) - assert.equal(countC2, 1) - }) - - it('should be able to reduce grouped data', async () => { - const reducedBy = await blockchain.indexReduceGroupBy('c_index', { created_on: { $gte: 0 } }, ['issuer', 'receiver', 'created_on']) - assert.deepEqual(reducedBy, [ - { op: 'UPDATE', issuer: 'D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 0, written_on: '9-0000092C94D0257C61A2504092440600487B2C8BEE73F9C8763C9F351543887D', writtenOn: 9, sig: 'MYWlBd2Hw3T/59BDz9HZECBuZ984C23F5lqUGluIUXsvXjsY4xKNqcN2x75s9rn++u4GEzZov6OznLZiHtbAAQ==', expires_on: 1552102327, expired_on: 1552102400, chainable_on: 1489419127 }, - { op: 'CREATE', issuer: 'EV4yZXAgmDd9rMsRCSH2MK7RHWty7CDB9tmHku3iRnEB', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 11, written_on: '11-000019EC1161FC9FB1848A58A3137B9CD9A919E86B2394B9682BBC3FADB1AF1F', writtenOn: 11, sig: 'plFuA1vgXJh0CQ9MVCmOgfTfFb5u3qICMfgxVJEsyco+lmZTxaKuruSsRdhw3YZgJgfU6YwC+ta/RcgLF6DvDA==', expires_on: 1556866334, expired_on: 0, chainable_on: 1494184082} - ]) - }) - - it('should be able to trim data', async () => { - // The number of records should decrease - await blockchain.indexTrim(10) - const countC1 = await blockchain.indexCount('c_index', { issuer: 'D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 0 }) - const countC2 = await blockchain.indexCount('c_index', { issuer: 'EV4yZXAgmDd9rMsRCSH2MK7RHWty7CDB9tmHku3iRnEB', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 11 }) - assert.equal(countC1, 0) // This index removes the lines marked `expired_on` - assert.equal(countC2, 1) - const reducedC2 = await blockchain.indexReduce('c_index', { issuer: 'EV4yZXAgmDd9rMsRCSH2MK7RHWty7CDB9tmHku3iRnEB', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 11 }) - assert.deepEqual(reducedC2, { op: 'CREATE', issuer: 'EV4yZXAgmDd9rMsRCSH2MK7RHWty7CDB9tmHku3iRnEB', receiver: 'G5P7k5t764ybGfFGLnEAwwMDz6y2U4afagAmyJXgKFyT', created_on: 11, written_on: '11-000019EC1161FC9FB1848A58A3137B9CD9A919E86B2394B9682BBC3FADB1AF1F', writtenOn: 11, sig: 'plFuA1vgXJh0CQ9MVCmOgfTfFb5u3qICMfgxVJEsyco+lmZTxaKuruSsRdhw3YZgJgfU6YwC+ta/RcgLF6DvDA==', expires_on: 1556866334, expired_on: 0, chainable_on: 1494184082}) - }) - }) - -})