diff --git a/app/lib/computation/blockchainContext.js b/app/lib/computation/blockchainContext.js index 54d31fb873cae1776382d1420e9378cbdbcbdfdc..62469c38de20fc30f8cfd02a957b1d32574a9e2f 100644 --- a/app/lib/computation/blockchainContext.js +++ b/app/lib/computation/blockchainContext.js @@ -243,10 +243,10 @@ function BlockchainContext() { }); this.revertCurrentBlock = () => co(function *() { - const current = yield that.current(); - logger.debug('Reverting block #%s...', current.number); - const res = yield that.revertBlock(current); - logger.debug('Reverted block #%s', current.number); + const head_1 = yield dal.bindexDAL.head(1); + logger.debug('Reverting block #%s...', head_1.number); + const res = yield that.revertBlock(head_1.number, head_1.hash); + logger.debug('Reverted block #%s', head_1.number); // Invalidates the head, since it has changed. yield refreshHead(); return res; @@ -264,9 +264,9 @@ function BlockchainContext() { logger.debug('Applied block #%s', block.number); }); - this.revertBlock = (block) => co(function *() { + this.revertBlock = (number, hash) => co(function *() { - const blockstamp = [block.number, block.hash].join('-'); + const blockstamp = [number, hash].join('-'); // Revert links const writtenOn = yield dal.cindexDAL.getWrittenOn(blockstamp); @@ -283,23 +283,27 @@ function BlockchainContext() { } // Revert nodes - yield undoMembersUpdate(block); + yield undoMembersUpdate(blockstamp); - yield dal.bindexDAL.removeBlock(block.number); + yield dal.bindexDAL.removeBlock(number); yield dal.mindexDAL.removeBlock(blockstamp); yield dal.iindexDAL.removeBlock(blockstamp); yield dal.cindexDAL.removeBlock(blockstamp); yield dal.sindexDAL.removeBlock(blockstamp); // Then: normal updates - const previousBlock = yield dal.getBlockByNumberAndHashOrNull(block.number - 1, block.previousHash || ''); + const previousBlock = yield dal.getBlock(number - 1); // Set the block as SIDE block (equivalent to removal from main branch) - yield dal.blockDAL.setSideBlock(block, previousBlock); + yield dal.blockDAL.setSideBlock(number, previousBlock); // Remove any source created for this block (both Dividend and Transaction). yield dal.removeAllSourcesOfBlock(blockstamp); - yield undoDeleteTransactions(block); + const block = yield dal.getBlockByBlockstampOrNull(blockstamp); + if (block) { + // For some reason the block might not exist (issue #827) + yield undoDeleteTransactions(block); + } }); const checkIssuer = (block) => co(function*() { @@ -442,23 +446,34 @@ function BlockchainContext() { }); }); - function undoMembersUpdate (block) { + function undoMembersUpdate (blockstamp) { return co(function *() { - // Undo 'join' which can be either newcomers or comebackers - for (const msRaw of block.joiners) { - let ms = Membership.statics.fromInline(msRaw, 'IN', conf.currency); - const idty = yield dal.getWrittenIdtyByPubkey(ms.issuer); - dal.wotb.setEnabled(false, idty.wotb_id); + const joiners = yield dal.iindexDAL.getWrittenOn(blockstamp); + for (const entry of joiners) { + // Undo 'join' which can be either newcomers or comebackers + // => equivalent to i_index.member = true AND i_index.op = 'UPDATE' + if (entry.member === true && entry.op === constants.IDX_UPDATE) { + const idty = yield dal.getWrittenIdtyByPubkey(entry.pub); + dal.wotb.setEnabled(false, idty.wotb_id); + } } - // Undo newcomers - for (let i = 0; i < block.identities.length; i++) { - // Does not matter which one it really was, we pop the last X identities - dal.wotb.removeNode(); + const newcomers = yield dal.iindexDAL.getWrittenOn(blockstamp); + for (const entry of newcomers) { + // Undo newcomers + // => equivalent to i_index.op = 'CREATE' + if (entry.op === constants.IDX_CREATE) { + // Does not matter which one it really was, we pop the last X identities + dal.wotb.removeNode(); + } } - // Undo excluded (make them become members again in wotb) - for (const pubkey of block.excluded) { - const idty = yield dal.getWrittenIdtyByPubkey(pubkey); - dal.wotb.setEnabled(true, idty.wotb_id); + const excluded = yield dal.iindexDAL.getWrittenOn(blockstamp); + for (const entry of excluded) { + // Undo excluded (make them become members again in wotb) + // => equivalent to m_index.member = false + if (entry.member === false && entry.op === constants.IDX_UPDATE) { + const idty = yield dal.getWrittenIdtyByPubkey(entry.pub); + dal.wotb.setEnabled(true, idty.wotb_id); + } } }); } diff --git a/app/lib/dal/sqliteDAL/AbstractIndex.js b/app/lib/dal/sqliteDAL/AbstractIndex.js index c4f00a27f836aebe46d6c4646f8b4e958ba36ac7..4ad733031a71368ad4ab55a686e7f000ecc43c1b 100644 --- a/app/lib/dal/sqliteDAL/AbstractIndex.js +++ b/app/lib/dal/sqliteDAL/AbstractIndex.js @@ -14,6 +14,8 @@ function AbstractIndex() { const that = this; + this.getWrittenOn = (blockstamp) => that.query('SELECT * FROM ' + that.table + ' WHERE written_on = ?', [blockstamp]); + this.trimRecords = (belowNumber) => co(function*() { const belowRecords = yield that.query('SELECT COUNT(*) as nbRecords, pub FROM ' + that.table + ' ' + 'WHERE CAST(written_on as int) < ? ' + diff --git a/app/lib/dal/sqliteDAL/BlockDAL.js b/app/lib/dal/sqliteDAL/BlockDAL.js index 31eb7fc2b6313cf762c85dbf2775b495753d83d0..dce074db5e38979f8e26a4ded5018617fb0429c6 100644 --- a/app/lib/dal/sqliteDAL/BlockDAL.js +++ b/app/lib/dal/sqliteDAL/BlockDAL.js @@ -147,8 +147,8 @@ function BlockDAL(driver) { }); } - this.setSideBlock = (block, previousBlock) => co(function *() { - yield that.query('UPDATE block SET fork = ? WHERE number = ? and hash = ?', [true, block.number, block.hash]); + this.setSideBlock = (number, previousBlock) => co(function *() { + yield that.query('UPDATE block SET fork = ? WHERE number = ?', [true, number]); current = previousBlock; }); diff --git a/server.js b/server.js index 954f082e9352e740cfbf3030a303f0b39a77f9ca..24e2692e51b7c569bd97bbb43ce9a68212602a4e 100644 --- a/server.js +++ b/server.js @@ -187,7 +187,21 @@ function Server (home, memoryOnly, overrideConf) { this.submitP = (obj, isInnerWrite) => Q.nbind(this.submit, this)(obj, isInnerWrite); - this.initDAL = () => this.dal.init(); + this.initDAL = () => co(function*() { + yield that.dal.init(); + // Maintenance + let head_1 = yield that.dal.bindexDAL.head(1); + if (head_1) { + // Case 1: b_index < block + yield that.dal.blockDAL.exec('DELETE FROM block WHERE NOT fork AND number > ' + head_1.number); + // Case 2: b_index > block + const current = yield that.dal.blockDAL.getCurrent(); + const nbBlocksToRevert = (head_1.number - current.number); + for (let i = 0; i < nbBlocksToRevert; i++) { + yield that.revert(); + } + } + }); this.recomputeSelfPeer = () => that.PeeringService.generateSelfPeer(that.conf, 0);