diff --git a/app/lib/blockchain/DuniterBlockchain.ts b/app/lib/blockchain/DuniterBlockchain.ts index 220ef7440fa19165effe224223b8f123a3bd775c..fa0a8cf0ad12b01d88d8163a5e8342b110dacd11 100644 --- a/app/lib/blockchain/DuniterBlockchain.ts +++ b/app/lib/blockchain/DuniterBlockchain.ts @@ -12,7 +12,7 @@ // GNU Affero General Public License for more details. import {MiscIndexedBlockchain} from "./MiscIndexedBlockchain" -import {IindexEntry, IndexEntry, Indexer, MindexEntry, SindexEntry} from "../indexer" +import {FullIindexEntry, IindexEntry, IndexEntry, Indexer, MindexEntry, SindexEntry} from "../indexer" import {BlockchainOperator} from "./interfaces/BlockchainOperator" import {ConfDTO} from "../dto/ConfDTO" import {BlockDTO} from "../dto/BlockDTO" @@ -26,16 +26,18 @@ import {MembershipDTO} from "../dto/MembershipDTO" import {TransactionDTO} from "../dto/TransactionDTO" import {CommonConstants} from "../common-libs/constants" import {FileDAL} from "../dal/fileDAL" +import {DBTx} from "../dal/sqliteDAL/TxsDAL" +import {DataErrors} from "../common-libs/errors" const _ = require('underscore') export class DuniterBlockchain extends MiscIndexedBlockchain { - constructor(blockchainStorage:BlockchainOperator, dal:any) { + constructor(blockchainStorage:BlockchainOperator, dal:FileDAL) { super(blockchainStorage, dal.mindexDAL, dal.iindexDAL, dal.sindexDAL, dal.cindexDAL) } - static async checkBlock(block:BlockDTO, withPoWAndSignature:boolean, conf: ConfDTO, dal:any) { + static async checkBlock(block:BlockDTO, withPoWAndSignature:boolean, conf: ConfDTO, dal:FileDAL) { const index = Indexer.localIndex(block, conf) if (withPoWAndSignature) { await CHECK.ASYNC.ALL_LOCAL(block, conf, index) @@ -175,7 +177,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { return { index, HEAD } } - async pushTheBlock(obj:BlockDTO, index:IndexEntry[], HEAD:DBHead | null, conf:ConfDTO, dal:any, logger:any) { + 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 { @@ -202,7 +204,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { // await supra.recordIndex(index) } - async saveBlockData(current:DBBlock, block:BlockDTO, conf:ConfDTO, dal:any, logger:any, index:IndexEntry[], HEAD:DBHead | null) { + 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); } @@ -262,7 +264,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { return dbb } - async saveParametersForRoot(block:BlockDTO, conf:ConfDTO, dal:any) { + async saveParametersForRoot(block:BlockDTO, conf:ConfDTO, dal:FileDAL) { if (block.parameters) { const bconf = BlockDTO.getConf(block) conf.c = bconf.c; @@ -292,9 +294,10 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - async createNewcomers(iindex:IindexEntry[], dal:any, logger:any) { - for (const entry of iindex) { - if (entry.op == CommonConstants.IDX_CREATE) { + async createNewcomers(iindex:IindexEntry[], dal:FileDAL, logger:any) { + for (const i of iindex) { + if (i.op == CommonConstants.IDX_CREATE) { + const entry = i as FullIindexEntry // Reserves a wotb ID entry.wotb_id = dal.wotb.addNode(); logger.trace('%s was affected wotb_id %s', entry.uid, entry.wotb_id); @@ -342,9 +345,14 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - async revertBlock(number:number, hash:string, dal:any) { + async revertBlock(number:number, hash:string, dal:FileDAL) { const blockstamp = [number, hash].join('-'); + const block = await dal.getBlockByBlockstampOrNull(blockstamp) + + if (!block) { + throw DataErrors[DataErrors.BLOCK_TO_REVERT_NOT_FOUND] + } // Revert links const writtenOn = await dal.cindexDAL.getWrittenOn(blockstamp); @@ -353,10 +361,10 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { const to = await dal.getWrittenIdtyByPubkeyForWotbID(entry.receiver); if (entry.op == CommonConstants.IDX_CREATE) { // We remove the created link - dal.wotb.removeLink(from.wotb_id, to.wotb_id, true); + dal.wotb.removeLink(from.wotb_id, to.wotb_id); } else { // We add the removed link - dal.wotb.addLink(from.wotb_id, to.wotb_id, true); + dal.wotb.addLink(from.wotb_id, to.wotb_id); } } @@ -374,7 +382,6 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { await dal.sindexDAL.removeBlock(blockstamp); // Then: normal updates - const block = await dal.getBlockByBlockstampOrNull(blockstamp); const previousBlock = await dal.getBlock(number - 1); // Set the block as SIDE block (equivalent to removal from main branch) await dal.blockDAL.setSideBlock(number, previousBlock); @@ -388,7 +395,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { return block } - async undoMembersUpdate(blockstamp:string, dal:any) { + 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 @@ -418,11 +425,11 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - async undoDeleteTransactions(block:BlockDTO, dal:any) { + async undoDeleteTransactions(block:DBBlock, dal:FileDAL) { for (const obj of block.transactions) { obj.currency = block.currency; let tx = TransactionDTO.fromJSONObject(obj) - await dal.saveTransaction(tx); + await dal.saveTransaction(DBTx.fromTransactionDTO(tx)) } } @@ -450,7 +457,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:any) { + 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) @@ -461,14 +468,14 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - async computeToBeRevoked(mindex:MindexEntry[], dal:any) { + 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, true); + await dal.setRevoked(revoked.pub) } } - async deleteTransactions(block:BlockDTO, dal:any) { + async deleteTransactions(block:BlockDTO, dal:FileDAL) { for (const obj of block.transactions) { obj.currency = block.currency; const tx = TransactionDTO.fromJSONObject(obj) @@ -498,7 +505,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { } } - static pushStatsForBlocks(blocks:BlockDTO[], dal:any) { + static pushStatsForBlocks(blocks:BlockDTO[], dal:FileDAL) { const stats: { [k:string]: { blocks: number[], lastParsedBlock:number }} = {}; // Stats for (const block of blocks) { @@ -529,7 +536,7 @@ export class DuniterBlockchain extends MiscIndexedBlockchain { return dal.pushStats(stats); } - async pushSideBlock(obj:BlockDTO, dal:any, logger:any) { + async pushSideBlock(obj:BlockDTO, dal:FileDAL, logger:any) { const start = Date.now(); const block = DBBlock.fromBlockDTO(BlockDTO.fromJSONObject(obj)) block.fork = true; diff --git a/app/lib/blockchain/Switcher.ts b/app/lib/blockchain/Switcher.ts index 4346fd1af0c8a1e5ef95f19f9b0994e35de0692f..9d9a7979a367741c76fd776c53fc295620a08322 100644 --- a/app/lib/blockchain/Switcher.ts +++ b/app/lib/blockchain/Switcher.ts @@ -12,6 +12,7 @@ // GNU Affero General Public License for more details. import {BlockDTO} from "../dto/BlockDTO" + export interface SwitchBlock { number:number @@ -22,7 +23,7 @@ export interface SwitchBlock { export interface SwitcherDao<T extends SwitchBlock> { - getCurrent(): Promise<T> + getCurrent(): Promise<T|null> getPotentials(numberStart:number, timeStart:number, maxNumber:number): Promise<T[]> getBlockchainBlock(number:number, hash:string): Promise<T|null> getSandboxBlock(number:number, hash:string): Promise<T|null> @@ -73,7 +74,7 @@ export class Switcher<T extends SwitchBlock> { * Find all the suites' HEAD that we could potentially fork on, in the current fork window. * @param current */ - async findPotentialSuitesHeads(current:T) { + async findPotentialSuitesHeads(current:{ number:number, medianTime:number }) { const numberStart = current.number - this.forkWindowSize const timeStart = current.medianTime - this.forkWindowSize * this.avgGenTime const suites = await this.findPotentialSuites(numberStart, timeStart) diff --git a/app/lib/common-libs/errors.ts b/app/lib/common-libs/errors.ts index 6286123f9cb4918ba9c1233001d4763d45ce4372..98f2763adc6268d0b3655f3ab0e156f47845f173 100644 --- a/app/lib/common-libs/errors.ts +++ b/app/lib/common-libs/errors.ts @@ -1,4 +1,13 @@ export enum DataErrors { + LOCAL_BLOCK_NOT_FOUND_FOR_CRAWLER, + BLOCKCHAIN_NOT_INITIALIZED_YET, + CANNOT_DETERMINATE_MEMBERSHIP_AGE, + CANNOT_DETERMINATE_IDENTITY_AGE, + CERT_BASED_ON_UNKNOWN_BLOCK, + NO_TRANSACTION_POSSIBLE_IF_NOT_CURRENT_BLOCK, + CANNOT_REAPPLY_NO_CURRENT_BLOCK, + CANNOT_REVERT_NO_CURRENT_BLOCK, + BLOCK_TO_REVERT_NOT_FOUND, MEMBER_NOT_FOUND } diff --git a/app/lib/computation/BlockchainContext.ts b/app/lib/computation/BlockchainContext.ts index 09b387a0152d830514b2d465f5a7029ce8e9b925..a1f3dcbc6cceb61cefde5acc238cad638d394936 100644 --- a/app/lib/computation/BlockchainContext.ts +++ b/app/lib/computation/BlockchainContext.ts @@ -16,6 +16,8 @@ import {BlockDTO} from "../dto/BlockDTO" import {DuniterBlockchain} from "../blockchain/DuniterBlockchain" import {QuickSynchronizer} from "./QuickSync" import {DBHead} from "../db/DBHead" +import {FileDAL} from "../dal/fileDAL" +import {DBBlock} from "../db/DBBlock" const _ = require('underscore'); const indexer = require('../indexer').Indexer @@ -24,7 +26,7 @@ const constants = require('../constants'); export class BlockchainContext { private conf:any - private dal:any + private dal:FileDAL private logger:any private blockchain:DuniterBlockchain private quickSynchronizer:QuickSynchronizer @@ -129,7 +131,7 @@ export class BlockchainContext { return dbb.toBlockDTO() } - async revertCurrentBlock(): Promise<BlockDTO> { + 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) @@ -146,7 +148,7 @@ export class BlockchainContext { throw constants.ERRORS.NO_POTENTIAL_FORK_AS_NEXT; } const block = forks[0]; - await this.checkAndAddBlock(block) + await this.checkAndAddBlock(BlockDTO.fromJSONObject(block)) this.logger.debug('Applied block #%s', block.number); } diff --git a/app/lib/computation/QuickSync.ts b/app/lib/computation/QuickSync.ts index 5d8853884b2da9e9e1d21816ec66a3469ae67483..fcc3f160040cf838a48cdbd271b559a829f076f3 100644 --- a/app/lib/computation/QuickSync.ts +++ b/app/lib/computation/QuickSync.ts @@ -15,8 +15,11 @@ import {DuniterBlockchain} from "../blockchain/DuniterBlockchain"; import {BlockDTO} from "../dto/BlockDTO"; import {DBTransaction} from "../db/DBTransaction"; -import {Indexer} from "../indexer"; +import {AccountsGarbagingDAL, Indexer} from "../indexer"; import {CurrencyConfDTO} from "../dto/ConfDTO"; +import {FileDAL} from "../dal/fileDAL" +import {DBBlock} from "../db/DBBlock" +import {DBTx} from "../dal/sqliteDAL/TxsDAL" const _ = require('underscore') const constants = require('../constants') @@ -32,7 +35,7 @@ let sync_expires: number[] = []; let sync_nextExpiring = 0; let sync_currConf: CurrencyConfDTO; const sync_memoryWallets: any = {} -const sync_memoryDAL = { +const sync_memoryDAL:AccountsGarbagingDAL = { getWallet: (conditions: string) => Promise.resolve(sync_memoryWallets[conditions] || { conditions, balance: 0 }), saveWallet: async (wallet: any) => { // Make a copy @@ -48,7 +51,7 @@ const sync_memoryDAL = { export class QuickSynchronizer { - constructor(private blockchain:DuniterBlockchain, private conf: any, private dal: any, private logger: any) { + constructor(private blockchain:DuniterBlockchain, private conf: any, private dal:FileDAL, private logger: any) { } async saveBlocksInMainBranch(blocks: BlockDTO[]): Promise<void> { @@ -57,13 +60,13 @@ export class QuickSynchronizer { await this.blockchain.saveParametersForRoot(blocks[0], this.conf, this.dal) } // Helper to retrieve a block with local cache - const getBlock = (number: number): Promise<BlockDTO> => { + const getBlock = async (number: number): Promise<BlockDTO> => { const firstLocalNumber = blocks[0].number; if (number >= firstLocalNumber) { let offset = number - firstLocalNumber; return Promise.resolve(blocks[offset]) } - return this.dal.getBlock(number); + return BlockDTO.fromJSONObject(await this.dal.getBlockWeHaveItForSure(number)) }; const getBlockByNumberAndHash = async (number: number, hash: string): Promise<BlockDTO> => { const block = await getBlock(number); @@ -79,7 +82,7 @@ export class QuickSynchronizer { } // Transactions recording await this.updateTransactionsForBlocks(blocks, getBlockByNumberAndHash); - await this.dal.blockDAL.saveBunch(blocks); + await this.dal.blockDAL.saveBunch(blocks.map(b => DBBlock.fromBlockDTO(b))); await DuniterBlockchain.pushStatsForBlocks(blocks, this.dal); } @@ -98,7 +101,7 @@ export class QuickSynchronizer { } txs = txs.concat(newOnes); } - return this.dal.updateTransactions(txs); + return this.dal.updateTransactions(txs.map(t => DBTx.fromTransactionDTO(t))) } async quickApplyBlocks(blocks:BlockDTO[], to: number): Promise<void> { @@ -127,14 +130,14 @@ export class QuickSynchronizer { sync_cindex = sync_cindex.concat(local_cindex); sync_mindex = sync_mindex.concat(local_mindex); - const HEAD = await Indexer.quickCompleteGlobalScope(block, sync_currConf, sync_bindex, sync_iindex, sync_mindex, sync_cindex, { + const HEAD = await Indexer.quickCompleteGlobalScope(block, sync_currConf, sync_bindex, sync_iindex, sync_mindex, sync_cindex, ({ getBlock: (number: number) => { return Promise.resolve(sync_allBlocks[number]); }, getBlockByBlockstamp: (blockstamp: string) => { return Promise.resolve(sync_allBlocks[parseInt(blockstamp)]); } - }); + }) as any); sync_bindex.push(HEAD); // Remember expiration dates diff --git a/app/lib/dal/fileDAL.ts b/app/lib/dal/fileDAL.ts index 557e0d422f021bf6cde21bded77d789c833137c1..1fb0e7f5ecaba3f2aa7d3df34d54521514e93eb9 100644 --- a/app/lib/dal/fileDAL.ts +++ b/app/lib/dal/fileDAL.ts @@ -172,11 +172,15 @@ export class FileDAL { return this.peerDAL.getPeersWithEndpointsLike('WS2P') } - async getBlock(number:number) { + async getBlock(number:number): Promise<DBBlock|null> { const block = await this.blockDAL.getBlock(number) return block || null; } + async getBlockWeHaveItForSure(number:number): Promise<DBBlock> { + return (await this.blockDAL.getBlock(number)) as DBBlock + } + getAbsoluteBlockByNumberAndHash(number:number, hash:string) { return this.blockDAL.getAbsoluteBlock(number, hash) } @@ -205,7 +209,7 @@ export class FileDAL { return this.getBlockByNumberAndHash(number, hash); } - async getBlockByNumberAndHash(number:number, hash:string) { + async getBlockByNumberAndHash(number:number, hash:string): Promise<DBBlock> { try { const block = await this.getBlock(number); if (!block || block.hash != hash) @@ -217,7 +221,7 @@ export class FileDAL { } } - async getBlockByNumberAndHashOrNull(number:number, hash:string) { + async getBlockByNumberAndHashOrNull(number:number, hash:string): Promise<DBBlock|null> { try { return await this.getBlockByNumberAndHash(number, hash) } catch (e) { @@ -238,7 +242,7 @@ export class FileDAL { async getCurrentBlockOrNull() { - let current = null; + let current:DBBlock|null = null; try { current = await this.getBlockCurrent() } catch (e) { @@ -850,20 +854,22 @@ export class FileDAL { } } - async saveBlock(block:BlockDTO) { - const dbb = DBBlock.fromBlockDTO(block) + async saveBlock(dbb:DBBlock) { dbb.wrong = false; await Promise.all([ this.saveBlockInFile(dbb), - this.saveTxsInFiles(block.transactions, block.number, block.medianTime) + this.saveTxsInFiles(dbb.transactions, dbb.number, dbb.medianTime) ]) } - async generateIndexes(block:DBBlock, conf:ConfDTO, index:IndexEntry[], HEAD:DBHead) { + async generateIndexes(block:BlockDTO, conf:ConfDTO, index:IndexEntry[], aHEAD:DBHead|null) { // We need to recompute the indexes for block#0 - if (!index || !HEAD || HEAD.number == 0) { + let HEAD:DBHead + if (!index || !aHEAD || aHEAD.number == 0) { index = indexer.localIndex(block, conf) HEAD = await indexer.completeGlobalScope(block, conf, index, this) + } else { + HEAD = aHEAD } let mindex = indexer.mindex(index); let iindex = indexer.iindex(index); @@ -903,7 +909,7 @@ export class FileDAL { return true; } - async trimSandboxes(block:DBBlock) { + async trimSandboxes(block:{ medianTime: number }) { await this.certDAL.trimExpiredCerts(block.medianTime); await this.msDAL.trimExpiredMemberships(block.medianTime); await this.idtyDAL.trimExpiredIdentities(block.medianTime); @@ -926,7 +932,8 @@ export class FileDAL { async saveTxsInFiles(txs:TransactionDTO[], block_number:number, medianTime:number) { return Promise.all(txs.map(async (tx) => { const sp = tx.blockstamp.split('-'); - tx.blockstampTime = (await this.getBlockByNumberAndHash(parseInt(sp[0]), sp[1])).medianTime; + const basedBlock = (await this.getBlockByNumberAndHash(parseInt(sp[0]), sp[1])) as DBBlock + tx.blockstampTime = basedBlock.medianTime; const txEntity = TransactionDTO.fromJSONObject(tx) txEntity.computeAllHashes(); return this.txsDAL.addLinked(TransactionDTO.fromJSONObject(txEntity), block_number, medianTime); @@ -1111,11 +1118,11 @@ export class FileDAL { } async cleanCaches() { - await _.values(this.newDals).map((dal:any) => dal.cleanCache && dal.cleanCache()) + await _.values(this.newDals).map((dal:Initiable) => dal.cleanCache && dal.cleanCache()) } async close() { - await _.values(this.newDals).map((dal:any) => dal.cleanCache && dal.cleanCache()) + await _.values(this.newDals).map((dal:Initiable) => dal.cleanCache && dal.cleanCache()) return this.sqliteDriver.closeConnection(); } diff --git a/app/lib/dal/fileDALs/AbstractCFS.ts b/app/lib/dal/fileDALs/AbstractCFS.ts index 729dee10fc1bb2b321dce4c638f08aebadf9c99c..128a441af4ad55135ca8425267ff347a4388e713 100644 --- a/app/lib/dal/fileDALs/AbstractCFS.ts +++ b/app/lib/dal/fileDALs/AbstractCFS.ts @@ -25,4 +25,7 @@ export abstract class AbstractCFS extends Initiable { super() this.coreFS = new CFSCore(rootPath, qioFS) } + + cleanCache() { + } } diff --git a/app/lib/dal/sqliteDAL/AbstractSQLite.ts b/app/lib/dal/sqliteDAL/AbstractSQLite.ts index 9a04110515cb69775dcd5b379c75f52f5f502f31..c7012733ef8543a4677b826d8e6a7c6b993139ef 100644 --- a/app/lib/dal/sqliteDAL/AbstractSQLite.ts +++ b/app/lib/dal/sqliteDAL/AbstractSQLite.ts @@ -199,6 +199,12 @@ export abstract class AbstractSQLite<T> extends Initiable { } } + /** + * To redefine if necessary in subclasses. + */ + cleanCache() { + } + private toConditionsArray(obj:any): string[] { return _.keys(obj).map((k:string) => { if (obj[k].$lte !== undefined) { diff --git a/app/lib/dal/sqliteDAL/BlockDAL.ts b/app/lib/dal/sqliteDAL/BlockDAL.ts index a595055e0ad00fa79937ad40755edfdfaa6e9b40..406d34a26225133f512fcf56f5bcfb4e6b01e71c 100644 --- a/app/lib/dal/sqliteDAL/BlockDAL.ts +++ b/app/lib/dal/sqliteDAL/BlockDAL.ts @@ -22,7 +22,7 @@ const IS_NOT_FORK = false; export class BlockDAL extends AbstractSQLite<DBBlock> { - private current: any + private current: DBBlock|null constructor(driver:SQLiteDriver) { super( @@ -97,14 +97,14 @@ export class BlockDAL extends AbstractSQLite<DBBlock> { if (!this.current) { this.current = (await this.query('SELECT * FROM block WHERE NOT fork ORDER BY number DESC LIMIT 1'))[0]; } - return Promise.resolve(this.current) + return this.current } - async getBlock(number:string | number) { + async getBlock(number:string | number): Promise<DBBlock|null> { return (await this.query('SELECT * FROM block WHERE number = ? and NOT fork', [parseInt(String(number))]))[0]; } - async getAbsoluteBlock(number:number, hash:string) { + async getAbsoluteBlock(number:number, hash:string): Promise<DBBlock|null> { return (await this.query('SELECT * FROM block WHERE number = ? and hash = ?', [number, hash]))[0]; } @@ -171,7 +171,7 @@ export class BlockDAL extends AbstractSQLite<DBBlock> { return await this.saveEntity(block); } - async setSideBlock(number:number, previousBlock:DBBlock) { + async setSideBlock(number:number, previousBlock:DBBlock|null) { await this.query('UPDATE block SET fork = ? WHERE number = ?', [true, number]); this.current = previousBlock; } diff --git a/app/lib/dal/sqliteDAL/Initiable.ts b/app/lib/dal/sqliteDAL/Initiable.ts index 6238920e82c5c68004dad6f2fc4eafc1e3d2dd51..c81fd7b7bf6f46ed257381a2241f8564054284b1 100644 --- a/app/lib/dal/sqliteDAL/Initiable.ts +++ b/app/lib/dal/sqliteDAL/Initiable.ts @@ -1,4 +1,5 @@ export abstract class Initiable { abstract init(): Promise<void> + abstract cleanCache(): void } diff --git a/app/lib/dal/sqliteDAL/MetaDAL.ts b/app/lib/dal/sqliteDAL/MetaDAL.ts index 4189e6bcf860c2f0fe5a3d8074767330df91e438..2d7e2abd7ada5aa7ef421319ef5c5ef6c0f41c0a 100644 --- a/app/lib/dal/sqliteDAL/MetaDAL.ts +++ b/app/lib/dal/sqliteDAL/MetaDAL.ts @@ -336,7 +336,7 @@ export class MetaDAL extends AbstractSQLite<DBMeta> { await mindexDAL.exec('ALTER TABLE m_index ADD COLUMN chainable_on INTEGER NULL;') const memberships = await mindexDAL.query('SELECT * FROM m_index WHERE op = ?', [CommonConstants.IDX_CREATE]) for (const ms of memberships) { - const reference = await blockDAL.getBlock(parseInt(ms.written_on.split('-')[0])) + const reference = (await blockDAL.getBlock(parseInt(ms.written_on.split('-')[0]))) as DBBlock const updateQuery = 'UPDATE m_index SET chainable_on = ' + (reference.medianTime + conf.msPeriod) + ' WHERE pub = \'' + ms.pub + '\' AND op = \'CREATE\'' await mindexDAL.exec(updateQuery) } @@ -371,7 +371,7 @@ export class MetaDAL extends AbstractSQLite<DBMeta> { let mindexDAL = new MIndexDAL(this.driverCopy) const memberships = await mindexDAL.query('SELECT * FROM m_index') for (const ms of memberships) { - const reference = await blockDAL.getBlock(parseInt(ms.written_on.split('-')[0])) + const reference = (await blockDAL.getBlock(parseInt(ms.written_on.split('-')[0]))) as DBBlock const msPeriod = conf.msWindow // It has the same value, as it was not defined on currency init const updateQuery = 'UPDATE m_index SET chainable_on = ' + (reference.medianTime + msPeriod) + ' WHERE pub = \'' + ms.pub + '\' AND written_on = \'' + ms.written_on + '\'' await mindexDAL.exec(updateQuery) diff --git a/app/lib/dal/sqliteDAL/index/BIndexDAL.ts b/app/lib/dal/sqliteDAL/index/BIndexDAL.ts index ee205dd490d68e2d81495238c249b928a7ffd04e..2b8537825305fec4f2bf995754acb0681bb76dc8 100644 --- a/app/lib/dal/sqliteDAL/index/BIndexDAL.ts +++ b/app/lib/dal/sqliteDAL/index/BIndexDAL.ts @@ -94,7 +94,7 @@ export class BIndexDAL extends AbstractSQLite<DBHead> { * Get HEAD~n * @param n Position */ - async head(n:number) { + async head(n:number): Promise<DBHead> { if (!n) { throw "Cannot read HEAD~0, which is the incoming block" } diff --git a/app/lib/dal/sqliteDAL/index/IIndexDAL.ts b/app/lib/dal/sqliteDAL/index/IIndexDAL.ts index 050f21e55da9060d595929350f2c6e783b1fa328..12c6391fb7662eeed4c163e6591956991cc08901 100644 --- a/app/lib/dal/sqliteDAL/index/IIndexDAL.ts +++ b/app/lib/dal/sqliteDAL/index/IIndexDAL.ts @@ -133,6 +133,10 @@ export class IIndexDAL extends AbstractIndex<IindexEntry> { return this.entityOrNull('uid', uid, retrieveOnPubkey) } + getFullFromPubkey(pub:string): Promise<FullIindexEntry> { + return this.entityOrNull('pub', pub) as Promise<FullIindexEntry> + } + getFullFromUID(uid:string): Promise<FullIindexEntry|null> { return this.entityOrNull('uid', uid, true) as Promise<FullIindexEntry|null> } diff --git a/app/lib/dal/sqliteDAL/index/SIndexDAL.ts b/app/lib/dal/sqliteDAL/index/SIndexDAL.ts index 13115dcec1233b67a8654b4552c80772b404e726..8161004f340ff0c561ce0c744e425be66e75e615 100644 --- a/app/lib/dal/sqliteDAL/index/SIndexDAL.ts +++ b/app/lib/dal/sqliteDAL/index/SIndexDAL.ts @@ -15,6 +15,7 @@ import {Indexer, SindexEntry} from "../../../indexer" import {SQLiteDriver} from "../../drivers/SQLiteDriver" import {AbstractIndex} from "../AbstractIndex" import {CommonConstants} from "../../../common-libs/constants" + const _ = require('underscore'); const constants = require('../../../constants'); @@ -109,7 +110,7 @@ export class SIndexDAL extends AbstractIndex<SindexEntry> { return this.getAvailableForConditions('%SIG(' + pubkey + ')%') } - async getAvailableForConditions(conditionsStr:string) { + async getAvailableForConditions(conditionsStr:string): Promise<{ amount:number, base:number }[]> { const potentials = await this.query('SELECT * FROM ' + this.table + ' s1 ' + 'WHERE s1.op = ? ' + 'AND conditions LIKE ? ' + diff --git a/app/lib/indexer.ts b/app/lib/indexer.ts index 5cfa75f8be50ecbb074ca69fcfb07c4b66550efa..90a626bf13e63619795e05ef569e911751a280fa 100644 --- a/app/lib/indexer.ts +++ b/app/lib/indexer.ts @@ -24,6 +24,8 @@ import {CommonConstants} from "./common-libs/constants" import {MembershipDTO} from "./dto/MembershipDTO" import {UnlockMetadata} from "./common-libs/txunlock" import {FileDAL} from "./dal/fileDAL" +import {DBWallet} from "./dal/sqliteDAL/WalletDAL" +import {DataErrors} from "./common-libs/errors" const _ = require('underscore'); @@ -167,6 +169,19 @@ function pushCindex(index: any[], entry: CindexEntry): void { index.push(entry) } +export interface AccountsGarbagingDAL { + getWallet: (conditions: string) => Promise<DBWallet> + saveWallet: (wallet: DBWallet) => Promise<void> + sindexDAL: { + getAvailableForConditions: (conditions: string) => any + } +} + +export interface BlockchainBlocksDAL { + getBlock(number: number): Promise<BlockDTO> + getBlockByBlockstamp(blockstamp: string): Promise<BlockDTO> +} + export class Indexer { static localIndex(block:BlockDTO, conf:CurrencyConfDTO): IndexEntry[] { @@ -451,7 +466,7 @@ export class Indexer { return index; } - static async quickCompleteGlobalScope(block: BlockDTO, conf: CurrencyConfDTO, bindex: DBHead[], iindex: IindexEntry[], mindex: MindexEntry[], cindex: CindexEntry[], dal: any) { + static async quickCompleteGlobalScope(block: BlockDTO, conf: CurrencyConfDTO, bindex: DBHead[], iindex: IindexEntry[], mindex: MindexEntry[], cindex: CindexEntry[], dal:FileDAL) { function range(start: number, end: number, property = ""): any { let theRange; @@ -543,7 +558,7 @@ export class Indexer { return HEAD; } - static async completeGlobalScope(block: BlockDTO, conf: ConfDTO, index: IndexEntry[], dal: any) { + static async completeGlobalScope(block: BlockDTO, conf: ConfDTO, index: IndexEntry[], dal:FileDAL) { const iindex = Indexer.iindex(index); const mindex = Indexer.mindex(index); @@ -909,7 +924,7 @@ export class Indexer { if (HEAD.number == 0 && ENTRY.created_on == '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855') { ENTRY.age = 0; } else { - let ref = await dal.getBlockByBlockstamp(ENTRY.created_on); + let ref = await dal.getBlockByBlockstamp(ENTRY.created_on as string); if (ref && blockstamp(ref.number, ref.hash) == ENTRY.created_on) { ENTRY.age = HEAD_1.medianTime - ref.medianTime; } else { @@ -1096,7 +1111,7 @@ export class Indexer { } // BR_G16 - static async prepareSpeed(HEAD: DBHead, head: (n:number) => Promise<BlockDTO>, conf: CurrencyConfDTO) { + static async prepareSpeed(HEAD: DBHead, head: (n:number) => Promise<DBHead>, conf: CurrencyConfDTO) { if (HEAD.number == 0) { HEAD.speed = 0; } else { @@ -1111,7 +1126,7 @@ export class Indexer { } // BR_G18 - static async preparePersonalizedPoW(HEAD: DBHead, HEAD_1: DBHead, range: (n:number,m:number)=>Promise<BlockDTO>, conf: ConfDTO) { + static async preparePersonalizedPoW(HEAD: DBHead, HEAD_1: DBHead, range: (n:number,m:number)=>Promise<DBHead[]>, conf: ConfDTO) { let nbPersonalBlocksInFrame, medianOfBlocksInFrame, blocksOfIssuer; let nbPreviousIssuers = 0, nbBlocksSince = 0; if (HEAD.number == 0) { @@ -1119,7 +1134,7 @@ export class Indexer { medianOfBlocksInFrame = 1; } else { const ranged = await range(1, HEAD_1.issuersFrame) - const blocksInFrame = _.filter(ranged, (b:BlockDTO) => b.number <= HEAD_1.number); + const blocksInFrame = _.filter(ranged, (b:DBHead) => b.number <= HEAD_1.number); const issuersInFrame = blocksInFrame.map((b:BlockDTO) => b.issuer); blocksOfIssuer = _.filter(blocksInFrame, (entry:BlockDTO) => entry.issuer == HEAD.issuer); nbPersonalBlocksInFrame = count(blocksOfIssuer); @@ -1148,12 +1163,12 @@ export class Indexer { } // BR_G19 - static async prepareIdentitiesAge(iindex: IindexEntry[], HEAD: DBHead, HEAD_1: DBHead, conf: CurrencyConfDTO, dal: any) { + static async prepareIdentitiesAge(iindex: IindexEntry[], HEAD: DBHead, HEAD_1: DBHead, conf: CurrencyConfDTO, dal:FileDAL) { await Promise.all(_.where(iindex, { op: constants.IDX_CREATE }).map(async (ENTRY: IindexEntry) => { if (HEAD.number == 0 && ENTRY.created_on == '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855') { ENTRY.age = 0; } else { - let ref = await dal.getBlockByBlockstamp(ENTRY.created_on); + let ref = await dal.getBlockByBlockstamp(ENTRY.created_on as string); if (ref && blockstamp(ref.number, ref.hash) == ENTRY.created_on) { ENTRY.age = HEAD_1.medianTime - ref.medianTime; } else { @@ -1164,7 +1179,7 @@ export class Indexer { } // BR_G22 - static async prepareMembershipsAge(mindex: MindexEntry[], HEAD: DBHead, HEAD_1: DBHead, conf: CurrencyConfDTO, dal: any) { + static async prepareMembershipsAge(mindex: MindexEntry[], HEAD: DBHead, HEAD_1: DBHead, conf: CurrencyConfDTO, dal:FileDAL) { await Promise.all(_.filter(mindex, (entry: MindexEntry) => !entry.revoked_on).map(async (ENTRY:MindexEntry) => { if (HEAD.number == 0 && ENTRY.created_on == '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855') { ENTRY.age = 0; @@ -1180,7 +1195,7 @@ export class Indexer { } // BR_G37 - static async prepareCertificationsAge(cindex: CindexEntry[], HEAD: DBHead, HEAD_1: DBHead, conf: CurrencyConfDTO, dal: any) { + static async prepareCertificationsAge(cindex: CindexEntry[], HEAD: DBHead, HEAD_1: DBHead, conf: CurrencyConfDTO, dal:FileDAL) { await Promise.all(cindex.map(async (ENTRY) => { if (HEAD.number == 0) { ENTRY.age = 0; @@ -1513,7 +1528,7 @@ export class Indexer { } // BR_G86 - static async ruleToBeKickedArePresent(iindex: IindexEntry[], dal:any) { + static async ruleToBeKickedArePresent(iindex: IindexEntry[], dal:FileDAL) { const toBeKicked = await dal.iindexDAL.getToBeKickedPubkeys(); for (const toKick of toBeKicked) { if (count(_.where(iindex, { pub: toKick, isBeingKicked: true })) !== 1) { @@ -1582,7 +1597,7 @@ export class Indexer { } // BR_G91 - static async ruleIndexGenDividend(HEAD: DBHead, dal: any) { + static async ruleIndexGenDividend(HEAD: DBHead, dal:FileDAL) { const dividends = []; if (HEAD.new_dividend) { const members = await dal.iindexDAL.getMembersPubkeys() @@ -1606,7 +1621,7 @@ export class Indexer { } // BR_G106 - static async ruleIndexGarbageSmallAccounts(HEAD: DBHead, sindex: SindexEntry[], dal: any) { + static async ruleIndexGarbageSmallAccounts(HEAD: DBHead, sindex: SindexEntry[], dal:AccountsGarbagingDAL) { const garbages = []; const accounts = Object.keys(sindex.reduce((acc: { [k:string]: boolean }, src) => { acc[src.conditions] = true; @@ -1654,7 +1669,7 @@ export class Indexer { } // BR_G92 - static async ruleIndexGenCertificationExpiry(HEAD: DBHead, dal:any) { + static async ruleIndexGenCertificationExpiry(HEAD: DBHead, dal:FileDAL) { const expiries = []; const certs = await dal.cindexDAL.findExpired(HEAD.medianTime); for (const CERT of certs) { @@ -1672,12 +1687,12 @@ export class Indexer { } // BR_G93 - static async ruleIndexGenMembershipExpiry(HEAD: DBHead, dal:any) { + static async ruleIndexGenMembershipExpiry(HEAD: DBHead, dal:FileDAL) { const expiries = []; const memberships: MindexEntry[] = reduceBy(await dal.mindexDAL.sqlFind({ expires_on: { $lte: HEAD.medianTime }, revokes_on: { $gt: HEAD.medianTime} }), ['pub']); for (const POTENTIAL of memberships) { - const MS = await dal.mindexDAL.getReducedMS(POTENTIAL.pub); + const MS = await dal.mindexDAL.getReducedMS(POTENTIAL.pub) as FullMindexEntry // We are sure because `memberships` already comes from the MINDEX const hasRenewedSince = MS.expires_on > HEAD.medianTime; if (!MS.expired_on && !hasRenewedSince) { expiries.push({ @@ -1694,11 +1709,11 @@ export class Indexer { } // BR_G94 - static async ruleIndexGenExclusionByMembership(HEAD: DBHead, mindex: MindexEntry[], dal:any) { + static async ruleIndexGenExclusionByMembership(HEAD: DBHead, mindex: MindexEntry[], dal:FileDAL) { const exclusions = []; const memberships = _.filter(mindex, (entry: MindexEntry) => entry.expired_on); for (const MS of memberships) { - const idty = await dal.iindexDAL.getFromPubkey(MS.pub); + const idty = await dal.iindexDAL.getFullFromPubkey(MS.pub); if (idty.member) { exclusions.push({ op: 'UPDATE', @@ -1713,7 +1728,7 @@ export class Indexer { } // BR_G95 - static async ruleIndexGenExclusionByCertificatons(HEAD: DBHead, cindex: CindexEntry[], iindex: IindexEntry[], conf: ConfDTO, dal: any) { + static async ruleIndexGenExclusionByCertificatons(HEAD: DBHead, cindex: CindexEntry[], iindex: IindexEntry[], conf: ConfDTO, dal:FileDAL) { const exclusions = []; const expiredCerts = _.filter(cindex, (c: CindexEntry) => c.expired_on > 0); for (const CERT of expiredCerts) { @@ -1722,7 +1737,7 @@ export class Indexer { const non_expired_global = await dal.cindexDAL.getValidLinksTo(CERT.receiver); if ((count(non_expired_global) - count(just_expired) + count(just_received)) < conf.sigQty) { const isInExcluded = _.filter(iindex, (i: IindexEntry) => i.member === false && i.pub === CERT.receiver)[0]; - const idty = await dal.iindexDAL.getFromPubkey(CERT.receiver); + const idty = (await dal.iindexDAL.getFromPubkey(CERT.receiver)) as FullIindexEntry if (!isInExcluded && idty.member) { exclusions.push({ op: 'UPDATE', @@ -1738,7 +1753,7 @@ export class Indexer { } // BR_G96 - static async ruleIndexGenImplicitRevocation(HEAD: DBHead, dal:any) { + static async ruleIndexGenImplicitRevocation(HEAD: DBHead, dal:FileDAL) { const revocations = []; const pending = await dal.mindexDAL.sqlFind({ revokes_on: { $lte: HEAD.medianTime}, revoked_on: { $null: true } }) for (const MS of pending) { @@ -1758,7 +1773,7 @@ export class Indexer { } // BR_G104 - static async ruleIndexCorrectMembershipExpiryDate(HEAD: DBHead, mindex: MindexEntry[], dal:any) { + static async ruleIndexCorrectMembershipExpiryDate(HEAD: DBHead, mindex: MindexEntry[], dal:FileDAL) { for (const MS of mindex) { if (MS.type == 'JOIN' || MS.type == 'ACTIVE') { let basedBlock = { medianTime: 0 }; @@ -1784,16 +1799,16 @@ export class Indexer { } // BR_G105 - static async ruleIndexCorrectCertificationExpiryDate(HEAD: DBHead, cindex: CindexEntry[], dal:any) { + static async ruleIndexCorrectCertificationExpiryDate(HEAD: DBHead, cindex: CindexEntry[], dal:FileDAL) { for (const CERT of cindex) { let basedBlock = { medianTime: 0 }; if (HEAD.number == 0) { basedBlock = HEAD; } else { if (HEAD.currency === 'gtest') { - basedBlock = await dal.getBlock(CERT.created_on); + basedBlock = await dal.getBlockWeHaveItForSure(CERT.created_on); } else { - basedBlock = await dal.getBlock(CERT.created_on); + basedBlock = await dal.getBlockWeHaveItForSure(CERT.created_on); } } CERT.expires_on += basedBlock.medianTime; @@ -1896,7 +1911,7 @@ function reduceBy(reducables: IndexEntry[], properties: string[]): any[] { return _.values(reduced).map((value: SindexEntry[]) => Indexer.DUP_HELPERS.reduce(value)); } -async function checkPeopleAreNotOudistanced (pubkeys: string[], newLinks: any, newcomers: string[], conf: ConfDTO, dal: any) { +async function checkPeopleAreNotOudistanced (pubkeys: string[], newLinks: any, newcomers: string[], conf: ConfDTO, dal:FileDAL) { // let wotb = dal.wotb; let wotb = dal.wotb.memCopy(); let current = await dal.getCurrentBlockOrNull(); @@ -1939,7 +1954,7 @@ async function checkPeopleAreNotOudistanced (pubkeys: string[], newLinks: any, n return error ? true : false; } -async function getNodeIDfromPubkey(nodesCache: any, pubkey: string, dal: any) { +async function getNodeIDfromPubkey(nodesCache: any, pubkey: string, dal:FileDAL) { let toNode = nodesCache[pubkey]; // Eventually cache the target nodeID if (toNode === null || toNode === undefined) { @@ -1985,7 +2000,7 @@ async function checkCertificationIsValid (block: BlockDTO, cert: CindexEntry, fi uid:string buid:string sig:string -}|null>, conf: ConfDTO, dal: any) { +}|null>, conf: ConfDTO, dal:FileDAL) { if (block.number == 0 && cert.created_on != 0) { throw Error('Number must be 0 for root block\'s certifications'); } else { @@ -1995,7 +2010,11 @@ async function checkCertificationIsValid (block: BlockDTO, cert: CindexEntry, fi if (block.number != 0) { try { - basedBlock = await dal.getBlock(cert.created_on); + const b = await dal.getBlock(cert.created_on) + if (!b) { + throw Error(DataErrors[DataErrors.CERT_BASED_ON_UNKNOWN_BLOCK]) + } + basedBlock = BlockDTO.fromJSONObject(b) } catch (e) { throw Error('Certification based on an unexisting block'); } diff --git a/app/lib/rules/global_rules.ts b/app/lib/rules/global_rules.ts index 7f9e44a39202eedd33da0940ac7233bade978ed3..ca5042161917d267220777ad3e4b75cc396cd604 100644 --- a/app/lib/rules/global_rules.ts +++ b/app/lib/rules/global_rules.ts @@ -102,7 +102,7 @@ export const GLOBAL_RULES_FUNCTIONS = { const outputs = tx.outputsAsObjects() let unlocks:any = {}; let sumOfInputs = 0; - let maxOutputBase = current.unitbase; + let maxOutputBase = current && current.unitbase || 0; for (const theUnlock of tx.unlocks) { let sp = theUnlock.split(':'); let index = parseInt(sp[0]); @@ -182,7 +182,7 @@ export const GLOBAL_RULES_FUNCTIONS = { export const GLOBAL_RULES_HELPERS = { // Functions used in an external context too - checkMembershipBlock: (ms:any, current:DBBlock, conf:ConfDTO, dal:FileDAL) => checkMSTarget(ms, current ? { number: current.number + 1} : { number: 0 }, conf, dal), + checkMembershipBlock: (ms:any, current:DBBlock|null, conf:ConfDTO, dal:FileDAL) => checkMSTarget(ms, current ? { number: current.number + 1} : { number: 0 }, conf, dal), checkCertificationIsValidInSandbox: (cert:any, current:BlockDTO, findIdtyFunc:any, conf:ConfDTO, dal:FileDAL) => { return checkCertificationShouldBeValid(current ? current : { number: 0, currency: '' }, cert, findIdtyFunc, conf, dal) @@ -196,7 +196,7 @@ export const GLOBAL_RULES_HELPERS = { return checkCertificationShouldBeValid(block, cert, findIdtyFunc, conf, dal) }, - isOver3Hops: async (member:any, newLinks:any, newcomers:string[], current:DBBlock, conf:ConfDTO, dal:FileDAL) => { + isOver3Hops: async (member:any, newLinks:any, newcomers:string[], current:DBBlock|null, conf:ConfDTO, dal:FileDAL) => { if (!current) { return Promise.resolve(false); } diff --git a/app/lib/rules/local_rules.ts b/app/lib/rules/local_rules.ts index bec4b70c7424835917b1d20340aa64c1da997fe9..d0d819cf7d148053c42b19af436ce777b5580619 100644 --- a/app/lib/rules/local_rules.ts +++ b/app/lib/rules/local_rules.ts @@ -524,7 +524,7 @@ export const LOCAL_RULES_HELPERS = { } }, - getMaxPossibleVersionNumber: async (current:DBBlock) => { + getMaxPossibleVersionNumber: async (current:DBBlock|null) => { // Looking at current blockchain, find what is the next maximum version we can produce // 1. We follow previous block's version diff --git a/app/modules/bma/lib/controllers/blockchain.ts b/app/modules/bma/lib/controllers/blockchain.ts index bfed41e47d7b2f162c9714e36d641f4872ef9653..b035728878b9ae53bd7b1b452ebb7b936cf0f2dd 100644 --- a/app/modules/bma/lib/controllers/blockchain.ts +++ b/app/modules/bma/lib/controllers/blockchain.ts @@ -29,6 +29,7 @@ import { HttpStat } from "../dtos" import {TransactionDTO} from "../../../../lib/dto/TransactionDTO" +import {DataErrors} from "../../../../lib/common-libs/errors" const _ = require('underscore'); const http2raw = require('../http2raw'); @@ -196,7 +197,10 @@ export class BlockchainBinding extends AbstractController { } async difficulties(): Promise<HttpDifficulties> { - const current = await this.server.dal.getCurrentBlockOrNull(); + const current = await this.server.dal.getCurrentBlockOrNull() + if (!current) { + throw Error(DataErrors[DataErrors.BLOCKCHAIN_NOT_INITIALIZED_YET]) + } const number = (current && current.number) || 0; const issuers = await this.server.dal.getUniqueIssuersBetween(number - 1 - current.issuersFrame, number - 1); const difficulties = []; diff --git a/app/modules/bma/lib/controllers/wot.ts b/app/modules/bma/lib/controllers/wot.ts index f88c06a52e92c4d17849e7dba19fe2c7fd0b5a81..f311bf891dd4f22a9a423b719185ab07629ff02f 100644 --- a/app/modules/bma/lib/controllers/wot.ts +++ b/app/modules/bma/lib/controllers/wot.ts @@ -121,7 +121,7 @@ export class WOTBinding extends AbstractController { for (const cert of certs) { const certifier = await this.server.dal.getWrittenIdtyByPubkeyForUidAndMemberAndCreatedOn(cert.from); if (certifier) { - let certBlock = await this.server.dal.getBlock(cert.block_number) + let certBlock = await this.server.dal.getBlockWeHaveItForSure(cert.block_number) theCerts.push({ pubkey: cert.from, uid: certifier.uid, @@ -215,7 +215,7 @@ export class WOTBinding extends AbstractController { for (const cert of certs) { const certified = await this.server.dal.getWrittenIdtyByPubkeyForUidAndMemberAndCreatedOn(cert.to); if (certified) { - let certBlock = await this.server.dal.getBlock(cert.block_number) + let certBlock = await this.server.dal.getBlockWeHaveItForSure(cert.block_number) theCerts.push({ pubkey: cert.to, uid: certified.uid, diff --git a/app/modules/crawler/lib/crawler.ts b/app/modules/crawler/lib/crawler.ts index 8766c226c9386d33d6342ad73cd24745248b4f71..0efe1174b3a1a502da992866e8f7ee6a95283c60 100644 --- a/app/modules/crawler/lib/crawler.ts +++ b/app/modules/crawler/lib/crawler.ts @@ -364,7 +364,7 @@ export class BlockCrawler { } try { - let current = await server.dal.getCurrentBlockOrNull(); + let current: DBBlock|null = await server.dal.getCurrentBlockOrNull(); if (current) { this.pullingEvent(server, 'start', current.number); this.logger && this.logger.info("Pulling blocks from the network..."); @@ -406,7 +406,7 @@ export class BlockCrawler { return Promise.resolve([node]) } async getLocalBlock(number: number): Promise<DBBlock> { - return server.dal.getBlock(number) + return server.dal.getBlockWeHaveItForSure(number) } async getRemoteBlock(thePeer: any, number: number): Promise<BlockDTO> { let block = null; @@ -429,7 +429,7 @@ export class BlockCrawler { } this.crawler.pullingEvent(server, 'applying', {number: block.number, last: this.lastDownloaded && this.lastDownloaded.number}); if (addedBlock) { - current = addedBlock; + current = DBBlock.fromBlockDTO(addedBlock); // Emit block events (for sharing with the network) only in forkWindowSize if (nodeCurrent && nodeCurrent.number - addedBlock.number < server.conf.forksize) { server.streamPush(addedBlock); diff --git a/app/modules/crawler/lib/sync.ts b/app/modules/crawler/lib/sync.ts index 71751c13f2eb1f098d70dc262f3c6780ce345521..4a2578ebf571fa2723b467337fe37f2475a4d5e9 100644 --- a/app/modules/crawler/lib/sync.ts +++ b/app/modules/crawler/lib/sync.ts @@ -30,7 +30,6 @@ import {hashf} from "../../../lib/common" import {ConfDTO} from "../../../lib/dto/ConfDTO" import {PeeringService} from "../../../service/PeeringService" -const util = require('util'); const _ = require('underscore'); const moment = require('moment'); const multimeter = require('multimeter'); @@ -142,7 +141,7 @@ export class Synchroniser extends stream.Duplex { //============ this.logger.info('Getting remote blockchain info...'); this.watcher.writeStatus('Connecting to ' + this.host + '...'); - const lCurrent:DBBlock = await this.dal.getCurrentBlockOrNull(); + const lCurrent:DBBlock|null = await this.dal.getCurrentBlockOrNull(); const localNumber = lCurrent ? lCurrent.number : -1; let rCurrent:BlockDTO if (isNaN(to)) { @@ -256,7 +255,7 @@ export class Synchroniser extends stream.Duplex { return [node] } async getLocalBlock(number: number): Promise<DBBlock> { - return this.dal.getBlock(number) + return this.dal.getBlockWeHaveItForSure(number) } async getRemoteBlock(thePeer: PeerDTO, number: number): Promise<BlockDTO> { let block = null; diff --git a/app/modules/prover/lib/blockGenerator.ts b/app/modules/prover/lib/blockGenerator.ts index 87af52071be917e027babd0ace8e48d6318d6990..f180c283ed65c6f71bf0102ff0e7c27c09538ce8 100644 --- a/app/modules/prover/lib/blockGenerator.ts +++ b/app/modules/prover/lib/blockGenerator.ts @@ -29,6 +29,7 @@ import {MembershipDTO} from "../../../lib/dto/MembershipDTO" import {BlockDTO} from "../../../lib/dto/BlockDTO" import {ConfDTO} from "../../../lib/dto/ConfDTO" import {FileDAL} from "../../../lib/dal/fileDAL" +import {DataErrors} from "../../../lib/common-libs/errors" const _ = require('underscore'); const moment = require('moment'); @@ -128,7 +129,10 @@ export class BlockGenerator { return this.createBlock(current, newcomers, leavers, newCertsFromWoT, revocations, exclusions, wereExcludeds, transactions, manualValues); } - private async findTransactions(current:DBBlock, options:{ dontCareAboutChaining?:boolean }) { + private async findTransactions(current:DBBlock|null, options:{ dontCareAboutChaining?:boolean }) { + if (!current) { + return [] + } const versionMin = current ? Math.min(CommonConstants.LAST_VERSION_FOR_TX, current.version) : CommonConstants.DOCUMENTS_VERSION; const txs = await this.dal.getTransactionsPending(versionMin); const transactions = []; @@ -160,9 +164,9 @@ export class BlockGenerator { return transactions; } - private async findLeavers(current:DBBlock) { + private async findLeavers(current:DBBlock|null) { const leaveData: { [pub:string]: { identity: { member:boolean }|null, ms: any, key: any, idHash: string } } = {}; - const memberships = await this.dal.findLeavers(current && current.medianTime); + const memberships = await this.dal.findLeavers((current && current.medianTime) || 0) const leavers:string[] = []; memberships.forEach((ms:any) => leavers.push(ms.issuer)); for (const ms of memberships) { @@ -187,7 +191,7 @@ export class BlockGenerator { return leaveData; } - private async findNewcomers(current:DBBlock, filteringFunc: (joinData: { [pub:string]: any }) => Promise<{ [pub:string]: any }>) { + private async findNewcomers(current:DBBlock|null, filteringFunc: (joinData: { [pub:string]: any }) => Promise<{ [pub:string]: any }>) { const preJoinData = await this.getPreJoinData(current); const joinData = await filteringFunc(preJoinData); const members = await this.dal.getMembers(); @@ -229,7 +233,7 @@ export class BlockGenerator { } } - private async checkWoTConstraints(block:{ number:number, joiners:string[], identities:string[] }, newLinks:any, current:DBBlock) { + private async checkWoTConstraints(block:{ number:number, joiners:string[], identities:string[] }, newLinks:any, current:DBBlock|null) { if (block.number < 0) { throw 'Cannot compute WoT constraint for negative block number'; } @@ -271,9 +275,9 @@ export class BlockGenerator { } } - private async getPreJoinData(current:DBBlock) { + private async getPreJoinData(current:DBBlock|null) { const preJoinData:{ [k:string]: PreJoin } = {} - const memberships = await this.dal.findNewcomers(current && current.medianTime) + const memberships = await this.dal.findNewcomers((current && current.medianTime) || 0) const joiners:string[] = []; memberships.forEach((ms:any) => joiners.push(ms.issuer)); for (const ms of memberships) { @@ -283,6 +287,9 @@ export class BlockGenerator { if (!msBasedBlock) { throw constants.ERRORS.BLOCKSTAMP_DOES_NOT_MATCH_A_BLOCK; } + if (!current) { + throw Error(DataErrors[DataErrors.CANNOT_DETERMINATE_MEMBERSHIP_AGE]) + } let age = current.medianTime - msBasedBlock.medianTime; if (age > this.conf.msWindow) { throw constants.ERRORS.TOO_OLD_MEMBERSHIP; @@ -348,7 +355,7 @@ export class BlockGenerator { return newCerts; } - async getSinglePreJoinData(current:DBBlock, idHash:string, joiners:string[]) { + async getSinglePreJoinData(current:DBBlock|null, idHash:string, joiners:string[]) { const identity = await this.dal.getGlobalIdentityByHashForJoining(idHash) let foundCerts = []; const vHEAD_1 = await this.mainContext.getvHEAD_1(); @@ -360,6 +367,9 @@ export class BlockGenerator { } else if (!identity.wasMember && identity.buid != CommonConstants.SPECIAL_BLOCK) { const idtyBasedBlock = await this.dal.getBlock(parseInt(identity.buid.split('-')[0])) + if (!current || !idtyBasedBlock) { + throw Error(DataErrors[DataErrors.CANNOT_DETERMINATE_IDENTITY_AGE]) + } const age = current.medianTime - idtyBasedBlock.medianTime; if (age > this.conf.idtyWindow) { throw constants.ERRORS.TOO_OLD_IDENTITY; @@ -439,7 +449,7 @@ export class BlockGenerator { } private async createBlock( - current:DBBlock, + current:DBBlock|null, joinData:{ [pub:string]: PreJoin }, leaveData:{ [pub:string]: LeaveData }, updates:any, @@ -658,7 +668,7 @@ export class BlockGenerator { block.dividend = vHEAD.dividend; block.unitbase = vHEAD.unitBase; } else { - block.unitbase = block.number == 0 ? 0 : current.unitbase; + block.unitbase = block.number == 0 ? 0 : (current as DBBlock).unitbase; // For sur current is not null, as UD is only on blocks# > 0 } // Rotation block.issuersCount = vHEAD.issuersCount; @@ -689,7 +699,7 @@ export class BlockGeneratorWhichProves extends BlockGenerator { } interface BlockGeneratorInterface { - findNewCertsFromWoT(current:DBBlock): Promise<any> + findNewCertsFromWoT(current:DBBlock|null): Promise<any> filterJoiners(preJoinData:any): Promise<any> } @@ -713,7 +723,7 @@ class NextBlockGenerator implements BlockGeneratorInterface { return this.server.dal } - async findNewCertsFromWoT(current:DBBlock) { + async findNewCertsFromWoT(current:DBBlock|null) { const updates:any = {}; const updatesToFrom:any = {}; const certs = await this.dal.certsFindNew(); diff --git a/app/modules/prover/lib/permanentProver.ts b/app/modules/prover/lib/permanentProver.ts index 9bf74f00054a6c36c5f58bf7cd686f15bdc94dea..411e873cc9c7d428f7f9edab83fb7952659855c6 100644 --- a/app/modules/prover/lib/permanentProver.ts +++ b/app/modules/prover/lib/permanentProver.ts @@ -140,7 +140,7 @@ export class PermanentProver { // The pushFIFO is here to get the difficulty level while excluding any new block to be resolved. // Without it, a new block could be added meanwhile and would make the difficulty wrongly computed. await this.server.BlockchainService.pushFIFO('generatingNextBlock', async () => { - const current = await this.server.dal.getCurrentBlockOrNull(); + const current = (await this.server.dal.getCurrentBlockOrNull()) as DBBlock const selfPubkey = this.server.keyPair.publicKey; if (!cancelAlreadyTriggered) { trial2 = await this.server.getBcContext().getIssuerPersonalizedDifficulty(selfPubkey) diff --git a/app/modules/ws2p/lib/WS2PBlockPuller.ts b/app/modules/ws2p/lib/WS2PBlockPuller.ts index 1a3445bc2ea16c02e58c492a768d1a5c91960464..638db4b9381070f3ca4d55274afcbbe8e1008797 100644 --- a/app/modules/ws2p/lib/WS2PBlockPuller.ts +++ b/app/modules/ws2p/lib/WS2PBlockPuller.ts @@ -84,7 +84,7 @@ class WS2PDao extends AbstractDAO { } async getLocalBlock(number: number): Promise<DBBlock> { - return this.server.dal.getBlock(number) + return this.server.dal.getBlockWeHaveItForSure(number) } async getRemoteBlock(thePeer: any, number: number): Promise<BlockDTO> { diff --git a/app/modules/ws2p/lib/WS2PCluster.ts b/app/modules/ws2p/lib/WS2PCluster.ts index f6e22e6edba8b6261e0d56fe43fcb71731cd2873..36603358ddfe57a9319811a22d640d8ec5e3828a 100644 --- a/app/modules/ws2p/lib/WS2PCluster.ts +++ b/app/modules/ws2p/lib/WS2PCluster.ts @@ -889,7 +889,7 @@ export class WS2PCluster { async pullBlocks() { let current:{number:number} = { number: -1 } - let newCurrent:{number:number} = { number: 0 } + let newCurrent:{number:number}|null = { number: 0 } while (current && newCurrent && newCurrent.number > current.number) { current = newCurrent await this.makeApullShot() diff --git a/app/modules/ws2p/lib/impl/WS2PReqMapperByServer.ts b/app/modules/ws2p/lib/impl/WS2PReqMapperByServer.ts index 49c04d411546fdc8b4a878b9d3624c35c985e4c4..ae0272b7f14375cbd697b87ecb9708274f6d5a4c 100644 --- a/app/modules/ws2p/lib/impl/WS2PReqMapperByServer.ts +++ b/app/modules/ws2p/lib/impl/WS2PReqMapperByServer.ts @@ -26,8 +26,8 @@ export class WS2PReqMapperByServer implements WS2PReqMapper { return this.server.BlockchainService.current() } - getBlock(number: number): Promise<BlockDTO> { - return Promise.resolve(BlockDTO.fromJSONObject(this.server.dal.getBlock(number))) + async getBlock(number: number): Promise<BlockDTO> { + return Promise.resolve(BlockDTO.fromJSONObject(await this.server.dal.getBlock(number))) } async getBlocks(count: number, from: number): Promise<BlockDTO[]> { @@ -35,6 +35,9 @@ export class WS2PReqMapperByServer implements WS2PReqMapper { throw 'Count is too high' } const current = await this.server.dal.getCurrentBlockOrNull() + if (!current) { + return [] + } count = Math.min(current.number - from + 1, count) if (!current || current.number < from) { return [] diff --git a/app/modules/ws2p/lib/interface/WS2PReqMapper.ts b/app/modules/ws2p/lib/interface/WS2PReqMapper.ts index f410e8145303accc678c95c87dfd6238d97a0539..b2575e4a26c5beb51d43b1fbfe67137b37d69822 100644 --- a/app/modules/ws2p/lib/interface/WS2PReqMapper.ts +++ b/app/modules/ws2p/lib/interface/WS2PReqMapper.ts @@ -12,10 +12,11 @@ // GNU Affero General Public License for more details. import {BlockDTO} from "../../../../lib/dto/BlockDTO" +import {DBBlock} from "../../../../lib/db/DBBlock" export interface WS2PReqMapper { - getCurrent(): Promise<BlockDTO> + getCurrent(): Promise<DBBlock|null> getBlock(number:number): Promise<BlockDTO> getBlocks(count:number, fromNumber:number): Promise<BlockDTO[]> getRequirementsOfPending(minCert:number): Promise<any> diff --git a/app/service/BlockchainService.ts b/app/service/BlockchainService.ts index b013a3f2db3b492ffff4bcb6afa1e8fbb1ce80f7..4a4f4726475e13b05e408982585925b1f3610462 100644 --- a/app/service/BlockchainService.ts +++ b/app/service/BlockchainService.ts @@ -28,6 +28,7 @@ import {CommonConstants} from "../lib/common-libs/constants" 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" "use strict"; @@ -73,8 +74,12 @@ export class BlockchainService extends FIFOService { constructor(private bcService:BlockchainService) {} - getCurrent(): Promise<BlockDTO> { - return this.bcService.current() + async getCurrent(): Promise<BlockDTO|null> { + const current = await this.bcService.current() + if (!current) { + return null + } + return BlockDTO.fromJSONObject(current) } async getPotentials(numberStart: number, timeStart: number, maxNumber:number): Promise<BlockDTO[]> { @@ -102,6 +107,9 @@ export class BlockchainService extends FIFOService { async revertTo(number: number): Promise<BlockDTO[]> { const blocks:BlockDTO[] = [] const current = await this.bcService.current(); + if (!current) { + throw Error(DataErrors[DataErrors.CANNOT_REVERT_NO_CURRENT_BLOCK]) + } for (let i = 0, count = current.number - number; i < count; i++) { const reverted = await this.bcService.mainContext.revertCurrentBlock() blocks.push(BlockDTO.fromJSONObject(reverted)) @@ -156,9 +164,12 @@ export class BlockchainService extends FIFOService { async branches() { const current = await this.current() + if (!current) { + throw Error(DataErrors[DataErrors.CANNOT_REVERT_NO_CURRENT_BLOCK]) + } const switcher = new Switcher(this.switcherDao, this.invalidForks, this.conf.avgGenTime, this.conf.forksize, this.conf.switchOnHeadAdvance, this.logger) const heads = await switcher.findPotentialSuitesHeads(current) - return heads.concat([current]) + return heads.concat([BlockDTO.fromJSONObject(current)]) } submitBlock(blockToAdd:any, noResolution = false): Promise<BlockDTO> { @@ -289,7 +300,7 @@ export class BlockchainService extends FIFOService { return all; } - async requirementsOfIdentity(idty:IdentityForRequirements, current:DBBlock, computeDistance = true): Promise<HttpIdentityRequirement> { + async requirementsOfIdentity(idty:IdentityForRequirements, current:DBBlock|null, computeDistance = true): Promise<HttpIdentityRequirement> { // TODO: this is not clear let expired = false; let outdistanced = false; @@ -401,13 +412,15 @@ export class BlockchainService extends FIFOService { const certs = newCerts[newcomer] || []; for (const cert of certs) { const block = await this.dal.getBlock(cert.block_number); - certsFromCerts.push({ - from: cert.from, - to: cert.to, - sig: cert.sig, - timestamp: block.medianTime, - expiresIn: 0 - }); + if (block) { + certsFromCerts.push({ + from: cert.from, + to: cert.to, + sig: cert.sig, + timestamp: block.medianTime, + expiresIn: 0 + }) + } } return certsFromLinks.concat(certsFromCerts).map(c => { c.expiresIn = Math.max(0, c.timestamp + this.conf.sigValidity - currentTime) @@ -429,11 +442,14 @@ export class BlockchainService extends FIFOService { return this.server.blockchain.saveParametersForRoot(block, this.conf, this.dal) } - async blocksBetween(from:number, count:number) { + async blocksBetween(from:number, count:number): Promise<DBBlock[]> { if (count > 5000) { throw 'Count is too high'; } const current = await this.current() + if (!current) { + return [] + } count = Math.min(current.number - from + 1, count); if (!current || current.number < from) { return []; diff --git a/app/service/IdentityService.ts b/app/service/IdentityService.ts index 342c8dc682674149f0800283874864fcaabf9c45..f4e5a2b2fdf8e0e8ae051794dbcece4587e4ee31 100644 --- a/app/service/IdentityService.ts +++ b/app/service/IdentityService.ts @@ -24,6 +24,7 @@ import {DBCert} from "../lib/dal/sqliteDAL/CertDAL" import {verify} from "../lib/common-libs/crypto/keyring" import {FIFOService} from "./FIFOService" import {MindexEntry} from "../lib/indexer" +import {DataErrors} from "../lib/common-libs/errors" "use strict"; const constants = require('../lib/constants'); @@ -198,13 +199,16 @@ export class IdentityService extends FIFOService { } if (!anErr) { try { - let basedBlock: { number:number, hash:string, medianTime?:number } = await this.dal.getBlock(cert.block_number); + let basedBlock: { number:number, hash:string, medianTime?:number }|null = await this.dal.getBlock(cert.block_number); if (cert.block_number == 0 && !basedBlock) { basedBlock = { number: 0, hash: 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855' }; } + if (!basedBlock) { + throw Error(DataErrors[DataErrors.CERT_BASED_ON_UNKNOWN_BLOCK]) + } const mCert:DBCert = { issuers: [cert.from], from: cert.from, diff --git a/app/service/MembershipService.ts b/app/service/MembershipService.ts index b0a75f51f02855e5ccdfaef4be37a17b6fd1dcb5..3dfe33fd6d9d27f261c30e088d34167539077795 100644 --- a/app/service/MembershipService.ts +++ b/app/service/MembershipService.ts @@ -19,6 +19,7 @@ import {LOCAL_RULES_HELPERS} from "../lib/rules/local_rules"; import {GLOBAL_RULES_HELPERS} from "../lib/rules/global_rules"; import {MembershipDTO} from "../lib/dto/MembershipDTO"; import {FIFOService} from "./FIFOService"; +import {DBBlock} from "../lib/db/DBBlock" const constants = require('../lib/constants'); @@ -38,7 +39,7 @@ export class MembershipService extends FIFOService { this.logger = require('../lib/logger').NewLogger(this.dal.profile); } - current() { + current(): Promise<DBBlock | null> { return this.dal.getCurrentBlockOrNull() } diff --git a/app/service/TransactionsService.ts b/app/service/TransactionsService.ts index c8608f6e7b47a63924f0ff69290fdf4a604271d0..ec84b57390c930909be67425cb408be94dca1172 100644 --- a/app/service/TransactionsService.ts +++ b/app/service/TransactionsService.ts @@ -20,6 +20,7 @@ import {GLOBAL_RULES_HELPERS} from "../lib/rules/global_rules"; import {DBTx} from "../lib/dal/sqliteDAL/TxsDAL"; import {FIFOService} from "./FIFOService"; import {GlobalFifoPromise} from "./GlobalFifoPromise"; +import {DataErrors} from "../lib/common-libs/errors" const constants = require('../lib/constants'); @@ -47,6 +48,9 @@ export class TransactionService extends FIFOService { this.logger.info('⬇ TX %s:%s from %s', tx.output_amount, tx.output_base, tx.issuers); const existing = await this.dal.getTxByHash(tx.hash); const current = await this.dal.getCurrentBlockOrNull(); + if (!current) { + throw Error(DataErrors[DataErrors.NO_TRANSACTION_POSSIBLE_IF_NOT_CURRENT_BLOCK]) + } if (existing) { throw constants.ERRORS.TX_ALREADY_PROCESSED; } diff --git a/server.ts b/server.ts index c7153ddd53abbb0b05beb891c5365dfe811e3a40..c37248f882dc3053520dd39b40a2281b46caa5ca 100644 --- a/server.ts +++ b/server.ts @@ -40,6 +40,7 @@ import {DBBlock} from "./app/lib/db/DBBlock" import {ProxiesConf} from './app/lib/proxy'; import {DBPeer} from "./app/lib/dal/sqliteDAL/PeerDAL" import {Directory, FileSystem} from "./app/lib/system/directory" +import {DataErrors} from "./app/lib/common-libs/errors" export interface HookableServer { generatorGetJoinData: (...args:any[]) => Promise<any> @@ -495,6 +496,9 @@ export class Server extends stream.Duplex implements HookableServer { async revertTo(number:number) { const current = await this.BlockchainService.current(); + if (!current) { + throw Error(DataErrors[DataErrors.CANNOT_REVERT_NO_CURRENT_BLOCK]) + } for (let i = 0, count = current.number - number; i < count; i++) { await this.BlockchainService.revertCurrentBlock() } @@ -519,6 +523,9 @@ export class Server extends stream.Duplex implements HookableServer { async reapplyTo(number:number) { const current = await this.BlockchainService.current(); + if (!current) { + throw Error(DataErrors[DataErrors.CANNOT_REAPPLY_NO_CURRENT_BLOCK]) + } if (current.number == number) { logger.warn('Already reached'); } else { @@ -632,7 +639,7 @@ export class Server extends stream.Duplex implements HookableServer { /** * Default WoT incoming data for new block. To be overriden by a module. */ - generatorGetJoinData(current:DBBlock, idtyHash:string , char:string): Promise<any> { + generatorGetJoinData(current:DBBlock|null, idtyHash:string , char:string): Promise<any> { return Promise.resolve({}) } diff --git a/test/integration/tools/toolbox.ts b/test/integration/tools/toolbox.ts index 40ccadd8836d052b1462d873aece31e780b15fc7..3edfff9c970f4e766548285b9d888b0cedce984a 100644 --- a/test/integration/tools/toolbox.ts +++ b/test/integration/tools/toolbox.ts @@ -40,6 +40,7 @@ import {RouterDependency} from "../../../app/modules/router" import {ProverDependency} from "../../../app/modules/prover/index" import {WS2PClient} from "../../../app/modules/ws2p/lib/WS2PClient" import {DBPeer} from "../../../app/lib/dal/sqliteDAL/PeerDAL" +import {DBBlock} from "../../../app/lib/db/DBBlock" const assert = require('assert'); const _ = require('underscore'); @@ -376,7 +377,7 @@ export class TestingServer { return this.server.home } - revert() { + revert(): Promise<DBBlock> { return this.server.revert() } diff --git a/test/integration/ws2p_client_limitations.ts b/test/integration/ws2p_client_limitations.ts index 4b16d9f03890068aae9326d02a8683d25de71486..06c6ac6a8df4511f8cd4a94a8070fe7e34163af8 100644 --- a/test/integration/ws2p_client_limitations.ts +++ b/test/integration/ws2p_client_limitations.ts @@ -115,10 +115,10 @@ describe("WS2P client limitations", function() { const currentS2 = await s2.BlockchainService.current() const currentS3 = await s3.BlockchainService.current() const currentS4 = await s4.BlockchainService.current() - assert.equal(currentS1.number, 2) - assert.equal(currentS2.number, 2) - assert.equal(currentS3.number, 2) - assert.equal(currentS4.number, 2) + assert.equal(currentS1 && currentS1.number, 2) + assert.equal(currentS2 && currentS2.number, 2) + assert.equal(currentS3 && currentS3.number, 2) + assert.equal(currentS4 && currentS4.number, 2) }) it('should be able to have a connected network on s2 start', async () => { diff --git a/test/integration/ws2p_cluster.ts b/test/integration/ws2p_cluster.ts index 13adbf4ed14c6aa38bfb387995fa2398db018738..a7b9919ab57e334ace32b73c61cbb8f8e988f0bc 100644 --- a/test/integration/ws2p_cluster.ts +++ b/test/integration/ws2p_cluster.ts @@ -21,7 +21,7 @@ import { } from "./tools/toolbox" import {WS2PCluster} from "../../app/modules/ws2p/lib/WS2PCluster" import {WS2PConstants} from "../../app/modules/ws2p/lib/constants" -import { TestUser } from './tools/TestUser'; +import {TestUser} from './tools/TestUser'; const assert = require('assert') @@ -94,9 +94,9 @@ describe("WS2P cluster", function() { const currentS1 = await s1.BlockchainService.current() const currentS2 = await s2.BlockchainService.current() const currentS3 = await s3.BlockchainService.current() - assert.equal(currentS1.number, 2) - assert.equal(currentS2.number, 2) - assert.equal(currentS3.number, 2) + assert.equal(currentS1 && currentS1.number, 2) + assert.equal(currentS2 && currentS2.number, 2) + assert.equal(currentS3 && currentS3.number, 2) }) it('should be able to have a connected network on s2 start', async () => { diff --git a/test/integration/ws2p_doc_sharing.ts b/test/integration/ws2p_doc_sharing.ts index b001ef00194768846f24827fb5667de44222abe4..ff8e132b4f961eb9b8ecf69121ba95c59ed0903e 100644 --- a/test/integration/ws2p_doc_sharing.ts +++ b/test/integration/ws2p_doc_sharing.ts @@ -11,7 +11,7 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -import { TestUser } from './tools/TestUser'; +import {TestUser} from './tools/TestUser'; import {simpleTestingConf, simpleTestingServer, simpleUser, simpleWS2PNetwork, TestingServer} from "./tools/toolbox" import {WS2PConstants} from "../../app/modules/ws2p/lib/constants" @@ -72,9 +72,9 @@ describe("WS2P doc sharing", function() { await s2.waitToHaveBlock(1) const b1s1 = await s1.BlockchainService.current() const b1s2 = await s2.BlockchainService.current() - assert.equal(b1s1.number, 1) - assert.equal(b1s2.number, 1) - assert.equal(b1s1.hash, b1s2.hash) + assert.equal(b1s1 && b1s1.number, 1) + assert.equal(b1s2 && b1s2.number, 1) + assert.equal(b1s1 && b1s1.hash, b1s2 && b1s2.hash) }) it('should see the identity, certs and memberships in the docpool', async () => { @@ -90,10 +90,10 @@ describe("WS2P doc sharing", function() { await s2.waitToHaveBlock(2) const b2s1 = await s1.BlockchainService.current() const b2s2 = await s2.BlockchainService.current() - assert.equal(b2s1.number, 2) - assert.equal(b2s2.number, 2) - assert.equal(b2s1.hash, b2s2.hash) - assert.equal(b2s2.joiners.length, 1) + assert.equal(b2s1 && b2s1.number, 2) + assert.equal(b2s2 && b2s2.number, 2) + assert.equal(b2s1 && b2s1.hash, b2s2 && b2s2.hash) + assert.equal(b2s2 && b2s2.joiners.length, 1) }) it('should see the transactions pending', async () => { @@ -110,10 +110,10 @@ describe("WS2P doc sharing", function() { await s2.waitToHaveBlock(3) const b3s1 = await s1.BlockchainService.current() const b3s2 = await s2.BlockchainService.current() - assert.equal(b3s1.number, 3) - assert.equal(b3s2.number, 3) - assert.equal(b3s1.hash, b3s2.hash) - assert.equal(b3s2.transactions.length, 1) + assert.equal(b3s1 && b3s1.number, 3) + assert.equal(b3s2 && b3s2.number, 3) + assert.equal(b3s1 && b3s1.hash, b3s2 && b3s2.hash) + assert.equal(b3s2 && b3s2.transactions.length, 1) }) it('should see the peer documents', async () => { diff --git a/test/integration/ws2p_docpool.ts b/test/integration/ws2p_docpool.ts index fabc209d205ec34a6b4781a0bee393cf427d1b65..c155be92296ff836c0f684349ad962d490890c76 100644 --- a/test/integration/ws2p_docpool.ts +++ b/test/integration/ws2p_docpool.ts @@ -66,8 +66,8 @@ describe("WS2P docpool pulling", function() { it('should have b#2 on s1 and s2', async () => { const currentS1 = await s1.BlockchainService.current() const currentS2 = await s2.BlockchainService.current() - assert.equal(currentS1.number, 2) - assert.equal(currentS2.number, 2) + assert.equal(currentS1 && currentS1.number, 2) + assert.equal(currentS2 && currentS2.number, 2) }) it('should be able to pull the docpool', async () => { @@ -85,7 +85,7 @@ describe("WS2P docpool pulling", function() { }) const currentS1 = await s1.BlockchainService.current() const currentS2 = await s2.BlockchainService.current() - assert.equal(currentS1.number, 2) - assert.equal(currentS2.number, 2) + assert.equal(currentS1 && currentS1.number, 2) + assert.equal(currentS2 && currentS2.number, 2) }) }) diff --git a/test/integration/ws2p_heads.ts b/test/integration/ws2p_heads.ts index a97f7ec425a679c5c17720ba5dc878b95ee31d88..d5a2b9fc1530e7849669d26cbbf6a41ec469fb61 100644 --- a/test/integration/ws2p_heads.ts +++ b/test/integration/ws2p_heads.ts @@ -72,8 +72,8 @@ describe("WS2P heads propagation", function() { it('should have b#2 on s1, s2 and s3', async () => { const currentS1 = await s1.BlockchainService.current() const currentS2 = await s2.BlockchainService.current() - assert.equal(currentS1.number, 2) - assert.equal(currentS2.number, 2) + assert.equal(currentS1 && currentS1.number, 2) + assert.equal(currentS2 && currentS2.number, 2) }) it('should be able to have a connected network on s2 start', async () => { diff --git a/test/integration/ws2p_network.ts b/test/integration/ws2p_network.ts index e241db09378c52f196d1b15b8b9d8a9d52bea48b..2d7a776a7de8fa859e6a3eada4ea6f2f290e8189 100644 --- a/test/integration/ws2p_network.ts +++ b/test/integration/ws2p_network.ts @@ -85,8 +85,8 @@ describe("WS2P network", function() { it('should have b#2 on s1 and s2', async () => { const currentS1 = await s1.BlockchainService.current() const currentS2 = await s2.BlockchainService.current() - assert.equal(currentS1.number, 2) - assert.equal(currentS2.number, 2) + assert.equal(currentS1 && currentS1.number, 2) + assert.equal(currentS2 && currentS2.number, 2) }) it('should be able to have a connected network on s2 start', async () => { diff --git a/test/integration/ws2p_pulling.ts b/test/integration/ws2p_pulling.ts index 4cd105a2e5e671f0607cb873f2c507a0b80b304a..8170c14fce57f12db59eb847be31862be8a5ac8d 100644 --- a/test/integration/ws2p_pulling.ts +++ b/test/integration/ws2p_pulling.ts @@ -79,16 +79,16 @@ describe("WS2P block pulling", function() { it('should have b#6 on s1, b#2 on s2', async () => { const currentS1 = await s1.BlockchainService.current() const currentS2 = await s2.BlockchainService.current() - assert.equal(currentS1.number, 6) - assert.equal(currentS2.number, 2) + assert.equal(currentS1 && currentS1.number, 6) + assert.equal(currentS2 && currentS2.number, 2) }) it('should be able to pull and have the same current block as a result', async () => { await cluster2.pullBlocks() const currentS1 = await s1.BlockchainService.current() const currentS2 = await s2.BlockchainService.current() - assert.equal(currentS1.number, 6) - assert.equal(currentS2.number, 6) + assert.equal(currentS1 && currentS1.number, 6) + assert.equal(currentS2 && currentS2.number, 6) }) it('should be able to pull pending identities', async () => { diff --git a/test/integration/ws2p_server_limitations.ts b/test/integration/ws2p_server_limitations.ts index 691345d6301374c78cc35419dbb28c6c10484082..88a15f9b19792b3c7a862d936b81576b8d0ad902 100644 --- a/test/integration/ws2p_server_limitations.ts +++ b/test/integration/ws2p_server_limitations.ts @@ -118,10 +118,10 @@ describe("WS2P server limitations", function() { const currentS2 = await s2.BlockchainService.current() const currentS3 = await s3.BlockchainService.current() const currentS4 = await s4.BlockchainService.current() - assert.equal(currentS1.number, 2) - assert.equal(currentS2.number, 2) - assert.equal(currentS3.number, 2) - assert.equal(currentS4.number, 2) + assert.equal(currentS1 && currentS1.number, 2) + assert.equal(currentS2 && currentS2.number, 2) + assert.equal(currentS3 && currentS3.number, 2) + assert.equal(currentS4 && currentS4.number, 2) }) it('should be able to have a connected network on s2 start', async () => {