diff --git a/app/lib/blockchain/duniterBlockchain.js b/app/lib/blockchain/duniterBlockchain.js index b2688c8ab33a1ae3c6defaa28ea08bbc4dd5813a..7edb9ecdbae37aabba97eb181681981edb1923e6 100644 --- a/app/lib/blockchain/duniterBlockchain.js +++ b/app/lib/blockchain/duniterBlockchain.js @@ -35,19 +35,19 @@ module.exports = class DuniterBlockchain extends MiscIndexedBlockchain { checkBlock(block, withPoWAndSignature, conf, dal) { return co(function*() { + const index = indexer.localIndex(block, conf) if (withPoWAndSignature) { - yield Q.nbind(rules.CHECK.ASYNC.ALL_LOCAL, rules, block, conf); + yield Q.nbind(rules.CHECK.ASYNC.ALL_LOCAL, rules, block, conf, index); } else { - yield Q.nbind(rules.CHECK.ASYNC.ALL_LOCAL_BUT_POW, rules, block, conf); + yield Q.nbind(rules.CHECK.ASYNC.ALL_LOCAL_BUT_POW, rules, block, conf, index); } - const index = indexer.localIndex(block, conf); + const HEAD = yield indexer.completeGlobalScope(block, conf, index, dal); + const HEAD_1 = yield dal.bindexDAL.head(1); const mindex = indexer.mindex(index); const iindex = indexer.iindex(index); const sindex = indexer.sindex(index); const cindex = indexer.cindex(index); - const HEAD = yield indexer.completeGlobalScope(block, conf, index, dal); - const HEAD_1 = yield dal.bindexDAL.head(1); // BR_G49 if (indexer.ruleVersion(HEAD, HEAD_1) === false) throw Error('ruleVersion'); // BR_G50 @@ -169,10 +169,11 @@ module.exports = class DuniterBlockchain extends MiscIndexedBlockchain { // Check the local rules // Enrich with the global index // Check the global rules + return { index, HEAD } }) } - pushBlock(obj, index, conf, dal, logger) { + pushBlock(obj, index, HEAD, conf, dal, logger) { // const supra = super const that = this return co(function*() { @@ -183,7 +184,7 @@ module.exports = class DuniterBlockchain extends MiscIndexedBlockchain { try { const currentBlock = yield dal.getCurrentBlockOrNull(); block.fork = false; - yield that.saveBlockData(currentBlock, block, conf, dal, logger); + yield that.saveBlockData(currentBlock, block, conf, dal, logger, index, HEAD); try { yield DuniterBlockchain.pushStatsForBlocks([block], dal); @@ -205,14 +206,14 @@ module.exports = class DuniterBlockchain extends MiscIndexedBlockchain { }) } - saveBlockData(current, block, conf, dal, logger) { + saveBlockData(current, block, conf, dal, logger, index, HEAD) { const that = this return co(function*() { if (block.number == 0) { yield that.saveParametersForRoot(block, conf, dal); } - const indexes = yield dal.generateIndexes(block, conf); + const indexes = yield dal.generateIndexes(block, conf, index, HEAD); // Newcomers yield that.createNewcomers(indexes.iindex, dal, logger); diff --git a/app/lib/computation/blockchainContext.js b/app/lib/computation/blockchainContext.js index 5b8343ae1dcad208d00d1282bef30738eee04f44..64292bdf6aad3e09c41dcb72dac21ca7188bc0a9 100644 --- a/app/lib/computation/blockchainContext.js +++ b/app/lib/computation/blockchainContext.js @@ -99,8 +99,8 @@ function BlockchainContext() { this.checkBlock = (block, withPoWAndSignature) => blockchain.checkBlock(block, withPoWAndSignature, conf, dal) - this.addBlock = (obj) => co(function*() { - const block = yield blockchain.pushBlock(obj, null, conf, dal, logger) + this.addBlock = (obj, index, HEAD) => co(function*() { + const block = yield blockchain.pushBlock(obj, index, HEAD, conf, dal, logger) vHEAD_1 = vHEAD = HEADrefreshed = null return block }) @@ -125,8 +125,8 @@ function BlockchainContext() { throw constants.ERRORS.NO_POTENTIAL_FORK_AS_NEXT; } const block = forks[0]; - yield that.checkBlock(block, constants.WITH_SIGNATURES_AND_POW); - yield that.addBlock(block); + const { index, HEAD } = yield that.checkBlock(block, constants.WITH_SIGNATURES_AND_POW); + yield that.addBlock(block, index, HEAD); logger.debug('Applied block #%s', block.number); }); diff --git a/app/lib/computation/quickSync.js b/app/lib/computation/quickSync.js index e0a58b02b2513ed8c1a499c6e4f3e1eb22eeea04..40d378344fe836bbfabe6da0e4b58e7eed97644e 100644 --- a/app/lib/computation/quickSync.js +++ b/app/lib/computation/quickSync.js @@ -238,8 +238,8 @@ module.exports = (blockchain, conf, dal, logger) => { yield dal.walletDAL.insertBatch(walletsToRecord) // Last block: cautious mode to trigger all the INDEX expiry mechanisms - yield blockchain.checkBlock(block, constants.WITH_SIGNATURES_AND_POW, conf, dal) - yield blockchain.pushBlock(block, null, conf, dal, logger) + const { index, HEAD } = yield blockchain.checkBlock(block, constants.WITH_SIGNATURES_AND_POW, conf, dal) + yield blockchain.pushBlock(block, index, HEAD, conf, dal, logger) // Clean temporary variables sync_bindex = []; @@ -262,4 +262,4 @@ module.exports = (blockchain, conf, dal, logger) => { return { saveBlocksInMainBranch, quickApplyBlocks } -} \ No newline at end of file +} diff --git a/app/lib/dal/fileDAL.js b/app/lib/dal/fileDAL.js index fd347be9d822c7d3283beb5354913b97d878c2b4..9886dbb14aaa86b716eea876cb2a14da1a58ac2f 100644 --- a/app/lib/dal/fileDAL.js +++ b/app/lib/dal/fileDAL.js @@ -531,13 +531,16 @@ function FileDAL(params) { ]; }); - this.generateIndexes = (block, conf) => co(function*() { - const index = indexer.localIndex(block, conf); + this.generateIndexes = (block, conf, index, HEAD) => co(function*() { + // We need to recompute the indexes for block#0 + if (!index || !HEAD || HEAD.number == 0) { + index = indexer.localIndex(block, conf) + HEAD = yield indexer.completeGlobalScope(block, conf, index, that) + } let mindex = indexer.mindex(index); let iindex = indexer.iindex(index); let sindex = indexer.sindex(index); let cindex = indexer.cindex(index); - const HEAD = yield indexer.completeGlobalScope(block, conf, index, that); sindex = sindex.concat(yield indexer.ruleIndexGenDividend(HEAD, that)); sindex = sindex.concat(yield indexer.ruleIndexGarbageSmallAccounts(HEAD, sindex, that)); cindex = cindex.concat(yield indexer.ruleIndexGenCertificationExpiry(HEAD, that)); diff --git a/app/lib/rules/index.js b/app/lib/rules/index.js index 9e1c0333a73bf8852747e44fb208e6aa26ee6ab5..989616d6b1afa55a2161c867ee1b6d681babf04a 100644 --- a/app/lib/rules/index.js +++ b/app/lib/rules/index.js @@ -20,7 +20,7 @@ _.extend(rules.HELPERS, global_rules.HELPERS); rules.ALIAS = { - ALL_LOCAL: (block, conf) => co(function *() { + ALL_LOCAL: (block, conf, index) => co(function *() { yield rules.LOCAL.checkParameters(block); yield rules.LOCAL.checkProofOfWork(block); yield rules.LOCAL.checkInnerHash(block); @@ -30,17 +30,17 @@ rules.ALIAS = { yield rules.LOCAL.checkBlockSignature(block); yield rules.LOCAL.checkBlockTimes(block, conf); yield rules.LOCAL.checkIdentitiesSignature(block); - yield rules.LOCAL.checkIdentitiesUserIDConflict(block, conf); - yield rules.LOCAL.checkIdentitiesPubkeyConflict(block, conf); - yield rules.LOCAL.checkIdentitiesMatchJoin(block, conf); - yield rules.LOCAL.checkMembershipUnicity(block, conf); - yield rules.LOCAL.checkRevokedUnicity(block, conf); - yield rules.LOCAL.checkRevokedAreExcluded(block, conf); + yield rules.LOCAL.checkIdentitiesUserIDConflict(block, conf, index); + yield rules.LOCAL.checkIdentitiesPubkeyConflict(block, conf, index); + yield rules.LOCAL.checkIdentitiesMatchJoin(block, conf, index); + yield rules.LOCAL.checkMembershipUnicity(block, conf, index); + yield rules.LOCAL.checkRevokedUnicity(block, conf, index); + yield rules.LOCAL.checkRevokedAreExcluded(block, conf, index); yield rules.LOCAL.checkMembershipsSignature(block); yield rules.LOCAL.checkPubkeyUnicity(block); - yield rules.LOCAL.checkCertificationOneByIssuer(block, conf); - yield rules.LOCAL.checkCertificationUnicity(block, conf); - yield rules.LOCAL.checkCertificationIsntForLeaverOrExcluded(block, conf); + yield rules.LOCAL.checkCertificationOneByIssuer(block, conf, index); + yield rules.LOCAL.checkCertificationUnicity(block, conf, index); + yield rules.LOCAL.checkCertificationIsntForLeaverOrExcluded(block, conf, index); yield rules.LOCAL.checkTxVersion(block); yield rules.LOCAL.checkTxIssuers(block); yield rules.LOCAL.checkTxSources(block); @@ -49,7 +49,7 @@ rules.ALIAS = { yield rules.LOCAL.checkTxSignature(block); }), - ALL_LOCAL_BUT_POW_AND_SIGNATURE: (block, conf) => co(function *() { + ALL_LOCAL_BUT_POW_AND_SIGNATURE: (block, conf, index) => co(function *() { yield rules.LOCAL.checkParameters(block); yield rules.LOCAL.checkInnerHash(block); yield rules.LOCAL.checkPreviousHash(block); @@ -57,17 +57,17 @@ rules.ALIAS = { yield rules.LOCAL.checkUnitBase(block); yield rules.LOCAL.checkBlockTimes(block, conf); yield rules.LOCAL.checkIdentitiesSignature(block); - yield rules.LOCAL.checkIdentitiesUserIDConflict(block, conf); - yield rules.LOCAL.checkIdentitiesPubkeyConflict(block, conf); - yield rules.LOCAL.checkIdentitiesMatchJoin(block, conf); - yield rules.LOCAL.checkMembershipUnicity(block, conf); - yield rules.LOCAL.checkRevokedUnicity(block, conf); - yield rules.LOCAL.checkRevokedAreExcluded(block, conf); + yield rules.LOCAL.checkIdentitiesUserIDConflict(block, conf, index); + yield rules.LOCAL.checkIdentitiesPubkeyConflict(block, conf, index); + yield rules.LOCAL.checkIdentitiesMatchJoin(block, conf, index); + yield rules.LOCAL.checkMembershipUnicity(block, conf, index); + yield rules.LOCAL.checkRevokedUnicity(block, conf, index); + yield rules.LOCAL.checkRevokedAreExcluded(block, conf, index); yield rules.LOCAL.checkMembershipsSignature(block); yield rules.LOCAL.checkPubkeyUnicity(block); - yield rules.LOCAL.checkCertificationOneByIssuer(block, conf); - yield rules.LOCAL.checkCertificationUnicity(block, conf); - yield rules.LOCAL.checkCertificationIsntForLeaverOrExcluded(block, conf); + yield rules.LOCAL.checkCertificationOneByIssuer(block, conf, index); + yield rules.LOCAL.checkCertificationUnicity(block, conf, index); + yield rules.LOCAL.checkCertificationIsntForLeaverOrExcluded(block, conf, index); yield rules.LOCAL.checkTxVersion(block); yield rules.LOCAL.checkTxIssuers(block); yield rules.LOCAL.checkTxSources(block); @@ -85,11 +85,11 @@ rules.CHECK = { }; function checkLocal(contract) { - return (b, conf, done) => { + return (b, conf, index, done) => { return co(function *() { try { const block = Block.fromJSON(b); - yield contract(block, conf); + yield contract(block, conf, index); done && done(); } catch (err) { if (done) return done(err); diff --git a/app/lib/rules/local_rules.js b/app/lib/rules/local_rules.js index f4a8f16a5d489aacb6ce3def8fb484027489f2d8..3b7d744dd86f6082a2236333eda58147731071a3 100644 --- a/app/lib/rules/local_rules.js +++ b/app/lib/rules/local_rules.js @@ -105,8 +105,7 @@ rules.FUNCTIONS = { return true; }), - checkIdentitiesUserIDConflict: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); + checkIdentitiesUserIDConflict: (block, conf, index) => co(function *() { const creates = indexer.iindexCreate(index); const uids = _.chain(creates).pluck('uid').uniq().value(); if (creates.length !== uids.length) { @@ -115,8 +114,7 @@ rules.FUNCTIONS = { return true; }), - checkIdentitiesPubkeyConflict: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); + checkIdentitiesPubkeyConflict: (block, conf, index) => co(function *() { const creates = indexer.iindexCreate(index); const pubkeys = _.chain(creates).pluck('pub').uniq().value(); if (creates.length !== pubkeys.length) { @@ -125,8 +123,7 @@ rules.FUNCTIONS = { return true; }), - checkIdentitiesMatchJoin: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); + checkIdentitiesMatchJoin: (block, conf, index) => co(function *() { const icreates = indexer.iindexCreate(index); const mcreates = indexer.mindexCreate(index); for (const icreate of icreates) { @@ -138,8 +135,7 @@ rules.FUNCTIONS = { return true; }), - checkRevokedAreExcluded: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); + checkRevokedAreExcluded: (block, conf, index) => co(function *() { const iindex = indexer.iindex(index); const mindex = indexer.mindex(index); const revocations = _.chain(mindex) @@ -155,17 +151,16 @@ rules.FUNCTIONS = { return true; }), - checkRevokedUnicity: (block, conf) => co(function *() { + checkRevokedUnicity: (block, conf, index) => co(function *() { try { - yield rules.FUNCTIONS.checkMembershipUnicity(block, conf); + yield rules.FUNCTIONS.checkMembershipUnicity(block, conf, index); } catch (e) { throw Error('A single revocation per member is allowed'); } return true; }), - checkMembershipUnicity: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); + checkMembershipUnicity: (block, conf, index) => co(function *() { const mindex = indexer.mindex(index); const pubkeys = _.chain(mindex).pluck('pub').uniq().value(); if (pubkeys.length !== mindex.length) { @@ -245,9 +240,8 @@ rules.FUNCTIONS = { return true; }), - checkCertificationOneByIssuer: (block, conf) => co(function *() { + checkCertificationOneByIssuer: (block, conf, index) => co(function *() { if (block.number > 0) { - const index = indexer.localIndex(block, conf); const cindex = indexer.cindex(index); const certFromA = _.uniq(cindex.map((row) => row.issuer)); if (certFromA.length !== cindex.length) { @@ -257,8 +251,7 @@ rules.FUNCTIONS = { return true; }), - checkCertificationUnicity: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); + checkCertificationUnicity: (block, conf, index) => co(function *() { const cindex = indexer.cindex(index); const certAtoB = _.uniq(cindex.map((row) => row.issuer + row.receiver)); if (certAtoB.length !== cindex.length) { @@ -267,8 +260,7 @@ rules.FUNCTIONS = { return true; }), - checkCertificationIsntForLeaverOrExcluded: (block, conf) => co(function *() { - const index = indexer.localIndex(block, conf); + checkCertificationIsntForLeaverOrExcluded: (block, conf, index) => co(function *() { const cindex = indexer.cindex(index); const iindex = indexer.iindex(index); const mindex = indexer.mindex(index); diff --git a/app/service/BlockchainService.js b/app/service/BlockchainService.js index 7e89e7968596671b48bf6ed95769a3cda0609c79..3cf7231fad9c51237bb4521f789cd150bd216215 100644 --- a/app/service/BlockchainService.js +++ b/app/service/BlockchainService.js @@ -130,9 +130,11 @@ function BlockchainService (server) { if (followsCurrent) { // try to add it on main blockchain if (doCheck) { - yield mainContext.checkBlock(obj, constants.WITH_SIGNATURES_AND_POW); + const { index, HEAD } = yield mainContext.checkBlock(obj, constants.WITH_SIGNATURES_AND_POW); + return yield mainContext.addBlock(obj, index, HEAD) + } else { + return yield mainContext.addBlock(obj) } - return yield mainContext.addBlock(obj) } else if (forkAllowed) { // add it as side chain if (current.number - obj.number + 1 >= conf.forksize) { diff --git a/test/fast/block_local.js b/test/fast/block_local.js index c3a796da1544fb1a9f7c2bc2f5fd40348f3c89a0..5d43d2e397b6036fd949ab642b2235b5f8827a00 100644 --- a/test/fast/block_local.js +++ b/test/fast/block_local.js @@ -2,6 +2,7 @@ const co = require('co'); const should = require('should'); const parsers = require('duniter-common').parsers; +const indexer = require('../../app/lib/indexer') const rules = require('../../app/lib/rules') const blocks = require('../data/blocks.js'); const parser = parsers.parseBlock; @@ -84,7 +85,8 @@ function test (rule, raw, expectedMessage) { try { let obj = parser.syncWrite(raw); let block = Block.fromJSON(obj); - yield rule(block, conf); // conf parameter is not always used + let index = indexer.localIndex(block, conf) + yield rule(block, conf, index); // conf parameter is not always used if (expectedMessage) { throw 'Test should have thrown an error'; }