diff --git a/app/lib/computation/blockGenerator.js b/app/lib/computation/blockGenerator.js deleted file mode 100644 index fb71891570a5591f0c0f0634fb3778c8674e50c7..0000000000000000000000000000000000000000 --- a/app/lib/computation/blockGenerator.js +++ /dev/null @@ -1,736 +0,0 @@ -"use strict"; -const _ = require('underscore'); -const co = require('co'); -const Q = require('q'); -const moment = require('moment'); -const inquirer = require('inquirer'); -const indexer = require('../dup/indexer'); -const rawer = require('../ucp/rawer'); -const hashf = require('../ucp/hashf'); -const constants = require('../constants'); -const rules = require('../rules/index'); -const keyring = require('../crypto/keyring'); -const Identity = require('../entity/identity'); -const Certification = require('../entity/certification'); -const Membership = require('../entity/membership'); -const Block = require('../entity/block'); -const Transaction = require('../entity/transaction'); - -module.exports = (mainContext, prover) => { - return new BlockGenerator(mainContext, prover); -}; - -function BlockGenerator(mainContext, prover) { - - const that = this; - let conf, dal, selfPubkey, logger; - - this.setConfDAL = (newConf, newDAL, newKeyPair) => { - dal = newDAL; - conf = newConf; - selfPubkey = newKeyPair.publicKey; - logger = require('../logger')(dal.profile); - }; - - this.nextBlock = (manualValues) => generateNextBlock(new NextBlockGenerator(mainContext, conf, dal), manualValues); - - this.manualRoot = () => co(function *() { - let current = yield dal.getCurrentBlockOrNull(); - if (current) { - throw 'Cannot generate root block: it already exists.'; - } - return generateNextBlock(new ManualRootGenerator()); - }); - - this.makeNextBlock = (block, trial, manualValues) => co(function *() { - const unsignedBlock = block || (yield that.nextBlock(manualValues)); - const trialLevel = trial || (yield mainContext.getIssuerPersonalizedDifficulty(selfPubkey)); - return prover.prove(unsignedBlock, trialLevel, (manualValues && manualValues.time) || null); - }); - - /** - * Generate next block, gathering both updates & newcomers - */ - const generateNextBlock = (generator, manualValues) => co(function *() { - const current = yield dal.getCurrentBlockOrNull(); - const revocations = yield dal.getRevocatingMembers(); - const exclusions = yield dal.getToBeKickedPubkeys(); - const newCertsFromWoT = yield generator.findNewCertsFromWoT(current); - const newcomersLeavers = yield findNewcomersAndLeavers(current, generator.filterJoiners); - const transactions = yield findTransactions(current); - const joinData = newcomersLeavers[2]; - const leaveData = newcomersLeavers[3]; - const newCertsFromNewcomers = newcomersLeavers[4]; - const certifiersOfNewcomers = _.uniq(_.keys(joinData).reduce((certifiers, newcomer) => { - return certifiers.concat(_.pluck(joinData[newcomer].certs, 'from')); - }, [])); - const certifiers = [].concat(certifiersOfNewcomers); - // Merges updates - _(newCertsFromWoT).keys().forEach(function(certified){ - newCertsFromWoT[certified] = newCertsFromWoT[certified].filter((cert) => { - // Must not certify a newcomer, since it would mean multiple certifications at same time from one member - const isCertifier = certifiers.indexOf(cert.from) != -1; - if (!isCertifier) { - certifiers.push(cert.from); - } - return !isCertifier; - }); - }); - _(newCertsFromNewcomers).keys().forEach((certified) => { - newCertsFromWoT[certified] = (newCertsFromWoT[certified] || []).concat(newCertsFromNewcomers[certified]); - }); - // Revocations - // Create the block - return createBlock(current, joinData, leaveData, newCertsFromWoT, revocations, exclusions, transactions, manualValues); - }); - - const findNewcomersAndLeavers = (current, filteringFunc) => co(function*() { - const newcomers = yield findNewcomers(current, filteringFunc); - const leavers = yield findLeavers(current); - - const cur = newcomers.current; - const newWoTMembers = newcomers.newWotMembers; - const finalJoinData = newcomers.finalJoinData; - const updates = newcomers.updates; - - return [cur, newWoTMembers, finalJoinData, leavers, updates]; - }); - - const findTransactions = (current) => co(function*() { - const versionMin = current ? Math.min(constants.LAST_VERSION_FOR_TX, current.version) : constants.DOCUMENTS_VERSION; - const txs = yield dal.getTransactionsPending(versionMin); - const transactions = []; - const passingTxs = []; - for (const obj of txs) { - const tx = new Transaction(obj, conf.currency); - const extractedTX = tx.getTransaction(); - try { - yield Q.nbind(rules.HELPERS.checkBunchOfTransactions, rules, passingTxs.concat(extractedTX)); - const nextBlockWithFakeTimeVariation = { medianTime: current.medianTime + 1 }; - yield rules.HELPERS.checkSingleTransaction(extractedTX, nextBlockWithFakeTimeVariation, conf, dal); - yield rules.HELPERS.checkTxBlockStamp(extractedTX, dal); - transactions.push(tx); - passingTxs.push(extractedTX); - logger.info('Transaction %s added to block', tx.hash); - } catch (err) { - logger.error(err); - const currentNumber = (current && current.number) || 0; - const blockstamp = extractedTX.blockstamp || (currentNumber + '-'); - const txBlockNumber = parseInt(blockstamp.split('-')[0]); - // 10 blocks before removing the transaction - if (currentNumber - txBlockNumber + 1 >= constants.TRANSACTION_MAX_TRIES) { - yield dal.removeTxByHash(extractedTX.hash); - } - } - } - return transactions; - }); - - const findLeavers = (current) => co(function*() { - const leaveData = {}; - const memberships = yield dal.findLeavers(); - const leavers = []; - memberships.forEach((ms) => leavers.push(ms.issuer)); - for (const ms of memberships) { - const leave = { identity: null, ms: ms, key: null, idHash: '' }; - leave.idHash = (hashf(ms.userid + ms.certts + ms.issuer) + "").toUpperCase(); - let block; - if (current) { - block = yield dal.getBlock(ms.number); - } - else { - block = {}; - } - const identity = yield dal.getIdentityByHashOrNull(leave.idHash); - const currentMembership = yield dal.mindexDAL.getReducedMS(ms.issuer); - const currentMSN = currentMembership ? parseInt(currentMembership.created_on) : -1; - if (identity && block && currentMSN < leave.ms.number && identity.member) { - // MS + matching cert are found - leave.identity = identity; - leaveData[identity.pubkey] = leave; - } - } - return leaveData; - }); - - const findNewcomers = (current, filteringFunc) => co(function*() { - const updates = {}; - const preJoinData = yield getPreJoinData(current); - const joinData = yield filteringFunc(preJoinData); - const members = yield dal.getMembers(); - const wotMembers = _.pluck(members, 'pubkey'); - // Checking step - const newcomers = _(joinData).keys(); - const nextBlockNumber = current ? current.number + 1 : 0; - try { - const realNewcomers = yield iteratedChecking(newcomers, (someNewcomers) => co(function*() { - const nextBlock = { - number: nextBlockNumber, - joiners: someNewcomers, - identities: _.filter(newcomers.map((pub) => joinData[pub].identity), { wasMember: false }).map((idty) => idty.pubkey) - }; - const newLinks = yield computeNewLinks(nextBlockNumber, someNewcomers, joinData, updates); - yield checkWoTConstraints(nextBlock, newLinks, current); - })); - const newLinks = yield computeNewLinks(nextBlockNumber, realNewcomers, joinData, updates); - const newWoT = wotMembers.concat(realNewcomers); - const finalJoinData = {}; - realNewcomers.forEach((newcomer) => { - // Only keep membership of selected newcomers - finalJoinData[newcomer] = joinData[newcomer]; - // Only keep certifications from final members - const keptCerts = []; - joinData[newcomer].certs.forEach((cert) => { - const issuer = cert.from; - if (~newWoT.indexOf(issuer) && ~newLinks[cert.to].indexOf(issuer)) { - keptCerts.push(cert); - } - }); - joinData[newcomer].certs = keptCerts; - }); - return { - current: current, - newWotMembers: wotMembers.concat(realNewcomers), - finalJoinData: finalJoinData, - updates: updates - } - } catch(err) { - logger.error(err); - throw err; - } - }); - - const checkWoTConstraints = (block, newLinks, current) => co(function*() { - if (block.number < 0) { - throw 'Cannot compute WoT constraint for negative block number'; - } - const newcomers = block.joiners.map((inlineMS) => inlineMS.split(':')[0]); - const realNewcomers = block.identities; - for (const newcomer of newcomers) { - if (block.number > 0) { - try { - // Will throw an error if not enough links - yield mainContext.checkHaveEnoughLinks(newcomer, newLinks); - // This one does not throw but returns a boolean - const isOut = yield rules.HELPERS.isOver3Hops(newcomer, newLinks, realNewcomers, current, conf, dal); - if (isOut) { - throw 'Key ' + newcomer + ' is not recognized by the WoT for this block'; - } - } catch (e) { - logger.debug(e); - throw e; - } - } - } - }); - - const iteratedChecking = (newcomers, checkWoTForNewcomers) => co(function*() { - const passingNewcomers = []; - let hadError = false; - for (const newcomer of newcomers) { - try { - yield checkWoTForNewcomers(passingNewcomers.concat(newcomer)); - passingNewcomers.push(newcomer); - } catch (err) { - hadError = hadError || err; - } - } - if (hadError) { - return yield iteratedChecking(passingNewcomers, checkWoTForNewcomers); - } else { - return passingNewcomers; - } - }); - - const getPreJoinData = (current) => co(function*() { - const preJoinData = {}; - const memberships = yield dal.findNewcomers(); - const joiners = []; - memberships.forEach((ms) =>joiners.push(ms.issuer)); - for (const ms of memberships) { - try { - if (ms.block != constants.BLOCK.SPECIAL_BLOCK) { - let msBasedBlock = yield dal.getBlockByBlockstampOrNull(ms.block); - if (!msBasedBlock) { - throw constants.ERRORS.BLOCKSTAMP_DOES_NOT_MATCH_A_BLOCK; - } - let age = current.medianTime - msBasedBlock.medianTime; - if (age > conf.msWindow) { - throw constants.ERRORS.TOO_OLD_MEMBERSHIP; - } - } - const idtyHash = (hashf(ms.userid + ms.certts + ms.issuer) + "").toUpperCase(); - const join = yield that.getSinglePreJoinData(current, idtyHash, joiners); - join.ms = ms; - const currentMembership = yield dal.mindexDAL.getReducedMS(ms.issuer); - const currentMSN = currentMembership ? parseInt(currentMembership.created_on) : -1; - if (!join.identity.revoked && currentMSN < parseInt(join.ms.number)) { - preJoinData[join.identity.pubkey] = join; - } - } catch (err) { - if (err && !err.uerr) { - logger.warn(err); - } - } - } - return preJoinData; - }); - - const computeNewLinks = (forBlock, theNewcomers, joinData, updates) => co(function *() { - let newCerts = yield that.computeNewCerts(forBlock, theNewcomers, joinData); - return that.newCertsToLinks(newCerts, updates); - }); - - this.newCertsToLinks = (newCerts, updates) => { - let newLinks = {}; - _.mapObject(newCerts, function(certs, pubkey) { - newLinks[pubkey] = _.pluck(certs, 'from'); - }); - _.mapObject(updates, function(certs, pubkey) { - newLinks[pubkey] = (newLinks[pubkey] || []).concat(_.pluck(certs, 'pubkey')); - }); - return newLinks; - }; - - this.computeNewCerts = (forBlock, theNewcomers, joinData) => co(function *() { - const newCerts = {}, certifiers = []; - const certsByKey = _.mapObject(joinData, function(val){ return val.certs; }); - for (const newcomer of theNewcomers) { - // New array of certifiers - newCerts[newcomer] = newCerts[newcomer] || []; - // Check wether each certification of the block is from valid newcomer/member - for (const cert of certsByKey[newcomer]) { - const isAlreadyCertifying = certifiers.indexOf(cert.from) !== -1; - if (!(isAlreadyCertifying && forBlock > 0)) { - if (~theNewcomers.indexOf(cert.from)) { - // Newcomer to newcomer => valid link - newCerts[newcomer].push(cert); - certifiers.push(cert.from); - } else { - let isMember = yield dal.isMember(cert.from); - // Member to newcomer => valid link - if (isMember) { - newCerts[newcomer].push(cert); - certifiers.push(cert.from); - } - } - } - } - } - return newCerts; - }); - - this.getSinglePreJoinData = (current, idHash, joiners) => co(function *() { - const identity = yield dal.getIdentityByHashOrNull(idHash); - let foundCerts = []; - const vHEAD_1 = yield mainContext.getvHEAD_1(); - if (!identity) { - throw 'Identity with hash \'' + idHash + '\' not found'; - } - if (current && identity.buid == constants.BLOCK.SPECIAL_BLOCK && !identity.wasMember) { - throw constants.ERRORS.TOO_OLD_IDENTITY; - } - else if (!identity.wasMember && identity.buid != constants.BLOCK.SPECIAL_BLOCK) { - const idtyBasedBlock = yield dal.getBlock(identity.buid); - const age = current.medianTime - idtyBasedBlock.medianTime; - if (age > conf.idtyWindow) { - throw constants.ERRORS.TOO_OLD_IDENTITY; - } - } - const idty = new Identity(identity); - idty.currency = conf.currency; - const createIdentity = idty.rawWithoutSig(); - const verified = keyring.verify(createIdentity, idty.sig, idty.pubkey); - if (!verified) { - throw constants.ERRORS.IDENTITY_WRONGLY_SIGNED; - } - const isIdentityLeaving = yield dal.isLeaving(idty.pubkey); - if (!isIdentityLeaving) { - if (!current) { - // Look for certifications from initial joiners - const certs = yield dal.certsNotLinkedToTarget(idHash); - foundCerts = _.filter(certs, function(cert){ - // Add 'joiners && ': special case when block#0 not written ANd not joiner yet (avoid undefined error) - return joiners && ~joiners.indexOf(cert.from); - }); - } else { - // Look for certifications from WoT members - let certs = yield dal.certsNotLinkedToTarget(idHash); - const certifiers = []; - for (const cert of certs) { - try { - const basedBlock = yield dal.getBlock(cert.block_number); - if (!basedBlock) { - throw 'Unknown timestamp block for identity'; - } - if (current) { - const age = current.medianTime - basedBlock.medianTime; - if (age > conf.sigWindow || age > conf.sigValidity) { - throw 'Too old certification'; - } - } - // Already exists a link not replayable yet? - let exists = yield dal.existsNonReplayableLink(cert.from, cert.to); - if (exists) { - throw 'It already exists a similar certification written, which is not replayable yet'; - } - // Already exists a link not chainable yet? - exists = yield dal.existsNonChainableLink(cert.from, vHEAD_1, conf.sigStock); - if (exists) { - throw 'It already exists a certification written which is not chainable yet'; - } - const isMember = yield dal.isMember(cert.from); - const doubleSignature = ~certifiers.indexOf(cert.from) ? true : false; - if (isMember && !doubleSignature) { - const isValid = yield rules.HELPERS.checkCertificationIsValidForBlock(cert, { number: current.number + 1, currency: current.currency }, identity, conf, dal); - if (isValid) { - certifiers.push(cert.from); - foundCerts.push(cert); - } - } - } catch (e) { - logger.warn(e.stack || e.message || e); - // Go on - } - } - } - } - return { - identity: identity, - key: null, - idHash: idHash, - certs: foundCerts - }; - }); - - const createBlock = (current, joinData, leaveData, updates, revocations, exclusions, transactions, manualValues) => { - return co(function *() { - - const vHEAD = yield mainContext.getvHeadCopy(); - const vHEAD_1 = yield mainContext.getvHEAD_1(); - const maxLenOfBlock = indexer.DUP_HELPERS.getMaxBlockSize(vHEAD); - let blockLen = 0; - // Revocations have an impact on exclusions - revocations.forEach((idty) => exclusions.push(idty.pubkey)); - // Prevent writing joins/updates for excluded members - exclusions = _.uniq(exclusions); - exclusions.forEach((excluded) => { - delete updates[excluded]; - delete joinData[excluded]; - delete leaveData[excluded]; - }); - _(leaveData).keys().forEach((leaver) => { - delete updates[leaver]; - delete joinData[leaver]; - }); - const block = new Block(); - block.number = current ? current.number + 1 : 0; - // Compute the new MedianTime - if (block.number == 0) { - block.medianTime = moment.utc().unix() - conf.rootoffset; - } - else { - block.medianTime = vHEAD.medianTime; - } - // Choose the version - block.version = (manualValues && manualValues.version) || (yield rules.HELPERS.getMaxPossibleVersionNumber(current)); - block.currency = current ? current.currency : conf.currency; - block.nonce = 0; - block.parameters = block.number > 0 ? '' : [ - conf.c, conf.dt, conf.ud0, - conf.sigPeriod, conf.sigStock, conf.sigWindow, conf.sigValidity, - conf.sigQty, conf.idtyWindow, conf.msWindow, conf.xpercent, conf.msValidity, - conf.stepMax, conf.medianTimeBlocks, conf.avgGenTime, conf.dtDiffEval, - (conf.percentRot == 1 ? "1.0" : conf.percentRot) - ].join(':'); - block.previousHash = current ? current.hash : ""; - block.previousIssuer = current ? current.issuer : ""; - if (selfPubkey) - block.issuer = selfPubkey; - // Members merkle - const joiners = _(joinData).keys(); - const previousCount = current ? current.membersCount : 0; - if (joiners.length == 0 && !current) { - throw constants.ERRORS.CANNOT_ROOT_BLOCK_NO_MEMBERS; - } - - // Kicked people - block.excluded = exclusions; - - /***** - * Priority 1: keep the WoT sane - */ - // Certifications from the WoT, to the WoT - _(updates).keys().forEach((certifiedMember) => { - const certs = updates[certifiedMember] || []; - certs.forEach((cert) => { - if (blockLen < maxLenOfBlock) { - block.certifications.push(new Certification(cert).inline()); - blockLen++; - } - }); - }); - // Renewed - joiners.forEach((joiner) => { - const data = joinData[joiner]; - // Join only for non-members - if (data.identity.member) { - if (blockLen < maxLenOfBlock) { - block.actives.push(new Membership(data.ms).inline()); - blockLen++; - } - } - }); - // Leavers - const leavers = _(leaveData).keys(); - leavers.forEach((leaver) => { - const data = leaveData[leaver]; - // Join only for non-members - if (data.identity.member) { - if (blockLen < maxLenOfBlock) { - block.leavers.push(new Membership(data.ms).inline()); - blockLen++; - } - } - }); - - /***** - * Priority 2: revoked identities - */ - revocations.forEach((idty) => { - if (blockLen < maxLenOfBlock) { - block.revoked.push([idty.pubkey, idty.revocation_sig].join(':')); - blockLen++; - } - }); - - /***** - * Priority 3: newcomers/renewcomers - */ - let countOfCertsToNewcomers = 0; - // Newcomers - // Newcomers + back people - joiners.forEach((joiner) => { - const data = joinData[joiner]; - // Identities only for never-have-been members - if (!data.identity.member && !data.identity.wasMember) { - block.identities.push(new Identity(data.identity).inline()); - } - // Join only for non-members - if (!data.identity.member) { - block.joiners.push(new Membership(data.ms).inline()); - } - }); - block.identities = _.sortBy(block.identities, (line) => { - const sp = line.split(':'); - return sp[2] + sp[3]; - }); - - // Certifications from the WoT, to newcomers - joiners.forEach((joiner) => { - const data = joinData[joiner] || []; - data.certs.forEach((cert) => { - countOfCertsToNewcomers++; - block.certifications.push(new Certification(cert).inline()); - }); - }); - - // Eventually revert newcomers/renewcomer - if (Block.statics.getLen(block) > maxLenOfBlock) { - for (let i = 0; i < block.identities.length; i++) { - block.identities.pop(); - block.joiners.pop(); - } - for (let i = 0; i < countOfCertsToNewcomers; i++) { - block.certifications.pop(); - } - } - - // Final number of members - block.membersCount = previousCount + block.joiners.length - block.excluded.length; - - vHEAD.membersCount = block.membersCount; - - /***** - * Priority 4: transactions - */ - block.transactions = []; - blockLen = Block.statics.getLen(block); - if (blockLen < maxLenOfBlock) { - transactions.forEach((tx) => { - const txLen = Transaction.statics.getLen(tx); - if (txLen <= constants.MAXIMUM_LEN_OF_COMPACT_TX && blockLen + txLen <= maxLenOfBlock && tx.version == constants.TRANSACTION_VERSION) { - block.transactions.push({ raw: tx.compact() }); - } - blockLen += txLen; - }); - } - - /** - * Finally handle the Universal Dividend - */ - block.powMin = vHEAD.powMin; - - // Universal Dividend - if (vHEAD.new_dividend) { - - // BR_G13 - // Recompute according to block.membersCount - indexer.prepareDividend(vHEAD, vHEAD_1, conf); - // BR_G14 - indexer.prepareUnitBase(vHEAD, vHEAD_1, conf); - - // Fix BR_G14 double call - vHEAD.unitBase = Math.min(vHEAD_1.unitBase + 1, vHEAD.unitBase); - - block.dividend = vHEAD.dividend; - block.unitbase = vHEAD.unitBase; - } else { - block.unitbase = block.number == 0 ? 0 : current.unitbase; - } - // Rotation - block.issuersCount = vHEAD.issuersCount; - block.issuersFrame = vHEAD.issuersFrame; - block.issuersFrameVar = vHEAD.issuersFrameVar; - // InnerHash - block.time = block.medianTime; - block.inner_hash = hashf(rawer.getBlockInnerPart(block)).toUpperCase(); - if (manualValues) { - _.extend(block, _.omit(manualValues, 'time')); - } - return block; - }); - } -} - -/** - * Class to implement strategy of automatic selection of incoming data for next block. - * @constructor - */ -function NextBlockGenerator(mainContext, conf, dal) { - - const logger = require('../logger')(dal.profile); - - this.findNewCertsFromWoT = (current) => co(function *() { - const updates = {}; - const updatesToFrom = {}; - const certs = yield dal.certsFindNew(); - const vHEAD_1 = yield mainContext.getvHEAD_1(); - for (const cert of certs) { - const targetIdty = yield dal.getIdentityByHashOrNull(cert.target); - // The identity must be known - if (targetIdty) { - const certSig = cert.sig; - // Do not rely on certification block UID, prefer using the known hash of the block by its given number - const targetBlock = yield dal.getBlock(cert.block_number); - // Check if writable - let duration = current && targetBlock ? current.medianTime - parseInt(targetBlock.medianTime) : 0; - if (targetBlock && duration <= conf.sigWindow) { - cert.sig = ''; - cert.currency = conf.currency; - cert.issuer = cert.from; - cert.idty_issuer = targetIdty.pubkey; - cert.idty_uid = targetIdty.uid; - cert.idty_buid = targetIdty.buid; - cert.idty_sig = targetIdty.sig; - cert.buid = current ? [cert.block_number, targetBlock.hash].join('-') : constants.BLOCK.SPECIAL_BLOCK; - const rawCert = Certification.statics.fromJSON(cert).getRaw(); - if (keyring.verify(rawCert, certSig, cert.from)) { - cert.sig = certSig; - let exists = false; - if (current) { - // Already exists a link not replayable yet? - exists = yield dal.existsNonReplayableLink(cert.from, cert.to); - } - if (!exists) { - // Already exists a link not chainable yet? - // No chainability block means absolutely nobody can issue certifications yet - exists = yield dal.existsNonChainableLink(cert.from, vHEAD_1, conf.sigStock); - if (!exists) { - // It does NOT already exists a similar certification written, which is not replayable yet - // Signatory must be a member - const isSignatoryAMember = yield dal.isMember(cert.from); - const isCertifiedANonLeavingMember = isSignatoryAMember && (yield dal.isMemberAndNonLeaver(cert.to)); - // Certified must be a member and non-leaver - if (isSignatoryAMember && isCertifiedANonLeavingMember) { - updatesToFrom[cert.to] = updatesToFrom[cert.to] || []; - updates[cert.to] = updates[cert.to] || []; - if (updatesToFrom[cert.to].indexOf(cert.from) == -1) { - updates[cert.to].push(cert); - updatesToFrom[cert.to].push(cert.from); - } - } - } - } - } - } - } - } - return updates; - }); - - this.filterJoiners = (preJoinData) => co(function*() { - const filtered = {}; - const filterings = []; - const filter = (pubkey) => co(function*() { - try { - // No manual filtering, takes all BUT already used UID or pubkey - let exists = yield rules.HELPERS.checkExistsUserID(preJoinData[pubkey].identity.uid, dal); - if (exists && !preJoinData[pubkey].identity.wasMember) { - throw 'UID already taken'; - } - exists = yield rules.HELPERS.checkExistsPubkey(pubkey, dal); - if (exists && !preJoinData[pubkey].identity.wasMember) { - throw 'Pubkey already taken'; - } - filtered[pubkey] = preJoinData[pubkey]; - } - catch (err) { - logger.warn(err); - } - }); - _.keys(preJoinData).forEach( (joinPubkey) => filterings.push(filter(joinPubkey))); - yield filterings; - return filtered; - }); -} - -/** - * Class to implement strategy of manual selection of root members for root block. - * @constructor - */ -function ManualRootGenerator() { - - this.findNewCertsFromWoT = () => Q({}); - - this.filterJoiners = (preJoinData) => co(function*() { - const filtered = {}; - const newcomers = _(preJoinData).keys(); - const uids = []; - newcomers.forEach((newcomer) => uids.push(preJoinData[newcomer].ms.userid)); - - if (newcomers.length > 0) { - return new Promise((resolve, reject) => { - inquirer.prompt([{ - type: "checkbox", - name: "uids", - message: "Newcomers to add", - choices: uids, - default: uids[0] - }], - (answers) => { - newcomers.forEach((newcomer) => { - if (~answers.uids.indexOf(preJoinData[newcomer].ms.userid)) - filtered[newcomer] = preJoinData[newcomer]; - }); - if (answers.uids.length == 0) - reject('No newcomer selected'); - else - resolve(filtered); - }); - }); - } else { - throw 'No newcomer found'; - } - }); -} diff --git a/app/lib/computation/blockProver.js b/app/lib/computation/blockProver.js deleted file mode 100644 index 66c320633ee8b8cb35195a0173ad09797ada4686..0000000000000000000000000000000000000000 --- a/app/lib/computation/blockProver.js +++ /dev/null @@ -1,245 +0,0 @@ -"use strict"; -const co = require('co'); -const _ = require('underscore'); -const constants = require('../constants'); -const engine = require('../pow/engine'); -const Block = require('../entity/block'); -const querablep = require('querablep'); - -const POW_FOUND = true; -const POW_NOT_FOUND_YET = false; - -module.exports = (server) => new BlockGenerator(server); - -function BlockGenerator(notifier) { - - let conf, pair, logger, waitResolve; - - let workerFarmPromise; - - function getWorker() { - return (workerFarmPromise || (workerFarmPromise = co(function*() { - return new WorkerFarm(); - }))); - } - - this.setConfDAL = (newConf, newDAL, newPair) => { - conf = newConf; - pair = newPair; - logger = require('../logger')('prover'); - }; - - const debug = process.execArgv.toString().indexOf('--debug') !== -1; - if(debug) { - //Set an unused port number. - process.execArgv = []; - } - - this.cancel = (gottenBlock) => co(function*() { - // If no farm was instanciated, tehre is nothing to do yet - if (workerFarmPromise) { - let farm = yield getWorker(); - if (farm.isComputing() && !farm.isStopping()) { - yield farm.stopPoW(gottenBlock); - } - if (waitResolve) { - waitResolve(); - waitResolve = null; - } - } - }); - - this.prove = function (block, difficulty, forcedTime) { - - if (waitResolve) { - waitResolve(); - waitResolve = null; - } - - const remainder = difficulty % 16; - const nbZeros = (difficulty - remainder) / 16; - const highMark = constants.PROOF_OF_WORK.UPPER_BOUND[remainder]; - - return co(function*() { - - let powFarm = yield getWorker(); - - if (block.number == 0) { - // On initial block, difficulty is the one given manually - block.powMin = difficulty; - } - - // Start - powFarm.setOnAlmostPoW(function(pow, matches, block, found) { - powEvent(found, pow); - if (matches && matches[1].length >= constants.PROOF_OF_WORK.MINIMAL_TO_SHOW_IN_LOGS) { - logger.info('Matched %s zeros %s with Nonce = %s for block#%s by %s', matches[1].length, pow, block.nonce, block.number, block.issuer.slice(0,6)); - } - }); - - block.nonce = 0; - logger.info('Generating proof-of-work with %s leading zeros followed by [0-' + highMark + ']... (CPU usage set to %s%) for block#%s', nbZeros, (conf.cpu * 100).toFixed(0), block.number, block.issuer.slice(0,6)); - const start = Date.now(); - let result = yield powFarm.askNewProof({ - newPoW: { conf: conf, block: block, zeros: nbZeros, highMark: highMark, forcedTime: forcedTime, - pair: pair.json() - } - }); - if (!result) { - logger.info('GIVEN proof-of-work for block#%s with %s leading zeros followed by [0-' + highMark + ']! stop PoW for %s', block.number, nbZeros, pair.publicKey.slice(0,6)); - throw 'Proof-of-work computation canceled because block received'; - } else { - const proof = result.block; - const testsCount = result.testsCount; - const duration = (Date.now() - start); - const testsPerSecond = (testsCount / (duration / 1000)).toFixed(2); - logger.info('Done: %s in %ss (%s tests, ~%s tests/s)', proof.hash, (duration / 1000).toFixed(2), testsCount, testsPerSecond); - logger.info('FOUND proof-of-work with %s leading zeros followed by [0-' + highMark + ']!', nbZeros); - return new Block(proof); - } - }); - }; - - this.changeCPU = (cpu) => co(function*() { - const farm = yield getWorker(); - yield farm.changeCPU(cpu); - }); - - this.changePoWPrefix = (prefix) => co(function*() { - const farm = yield getWorker(); - yield farm.changePoWPrefix(prefix); - }); - - function powEvent(found, hash) { - notifier && notifier.push({ pow: { found, hash } }); - } - - function WorkerFarm() { - // Create - const that = this; - // We use as much cores as available, but not more than CORES_MAXIMUM_USE_IN_PARALLEL - const cores = require('os').cpus().slice(0, constants.CORES_MAXIMUM_USE_IN_PARALLEL); - // Each worker has his own chunk of possible nonces - const workers = cores.map((c, index) => new Worker((index + 1), (index + 1) * constants.NONCE_RANGE, pair.publicKey)); - - let powPromise = null; - let stopPromise = null; - - this.changeCPU = (cpu) => Promise.all(workers.map((worker) => worker.changeConf({ cpu }))); - - this.changePoWPrefix = (prefix) => Promise.all(workers.map((worker) => worker.changeConf({ prefix }))); - - this.isComputing = () => powPromise !== null && !powPromise.isResolved(); - - this.isStopping = () => stopPromise !== null && !stopPromise.isResolved(); - - const whenReady = () => Promise.all(workers.map((worker) => worker.whenReady())); - - this.stopPoW = (gottenBlock) => { - stopPromise = querablep(Promise.all(workers.map((worker) => worker.stopPoW(gottenBlock)))); - return stopPromise; - }; - - this.askNewProof = (stuff) => co(function*() { - yield whenReady(); - // Starts a new race to find the PoW - const races = workers.map((worker) => querablep(worker.askNewProof(_.clone(stuff)))); - powPromise = querablep(Promise.race(races)); - // Wait for the PoW to be either found or canceled - let res = yield powPromise; - if (res) { - let engineNumber = races.reduce((doneIndex, obj, index) => { - if (doneIndex !== null) return doneIndex; - if (races[index].isResolved()) { - return index + 1; - } - return null; - }, null); - logger.info('ENGINE #%s HAS FOUND A PROOF', engineNumber); - } - // Ask for stopping the other engines - that.stopPoW(); - // But also give the answer in the **same time**, without waiting for effective stop of the engines - return (res && res.pow); - }); - - this.setOnAlmostPoW = (onPoW) => workers.map((worker) => worker.setOnAlmostPoW(onPoW)); - } - - function Worker(id, nonceBeginning) { - - const theEngine = engine(); - - let onAlmostPoW, prefix = 0; - - const checkPoWandNotify = (hash, block, found) => { - const matches = hash.match(/^(0{2,})[^0]/); - if (matches && onAlmostPoW) { - onAlmostPoW(hash, matches, block, found); - } - }; - - this.whenReady = () => this.stopPoW(); - - this.changeConf = (conf) => co(function*() { - if (conf.prefix) { - prefix = conf.prefix; - } - logger.info('Changing conf to: %s on engine#%s', JSON.stringify(conf), id); - theEngine.setValue('conf', conf ); - }); - - /** - * Eventually stops the engine PoW if one was computing - */ - this.stopPoW = () => { - logger.info('Stop proof-of-work worker #%s', id); - return theEngine.cancel(); - }; - - /** - * Starts a new computation of PoW - * @param stuff The necessary data for computing the PoW - */ - this.askNewProof = (stuff) => co(function*() { - // Keep track of PoW advancement - theEngine.setOnInfoMessage((message) => { - if (message.error) { - logger.error('Error in engine#%s:', id, message.error); - } else if (message.pow) { - // A message about the PoW - const msg = message.pow; - if (!msg.canceled) { - checkPoWandNotify(msg.pow, msg.block, POW_NOT_FOUND_YET); - } - } - }); - // Keep the engine alive as long as it hasn't found the proof OR hasn't been canceled - let interval = setInterval(() => { - return theEngine.status(); - }, constants.ENGINE_IDLE_INTERVAL); - // Starts the PoW - const res = yield theEngine.prove( - stuff.newPoW.block, - nonceBeginning, - stuff.newPoW.zeros, - stuff.newPoW.highMark, - stuff.newPoW.pair, - stuff.newPoW.forcedTime, - stuff.newPoW.conf.medianTimeBlocks, - stuff.newPoW.conf.avgGenTime, - stuff.newPoW.conf.cpu, - prefix - ); - clearInterval(interval); - if (res) { - checkPoWandNotify(res.pow.pow, res.pow.block, POW_FOUND); - } - return res; - }); - - this.setOnAlmostPoW = function(onPoW) { - onAlmostPoW = onPoW; - }; - } -} diff --git a/app/lib/computation/permanentProver.js b/app/lib/computation/permanentProver.js deleted file mode 100644 index 5988a265d1a836f96b4ab7883766320bbf749daa..0000000000000000000000000000000000000000 --- a/app/lib/computation/permanentProver.js +++ /dev/null @@ -1,172 +0,0 @@ -"use strict"; - -const co = require('co'); -const constants = require('../constants'); -const dos2unix = require('../system/dos2unix'); -const parsers = require('../streams/parsers'); - -module.exports = (server) => new PermanentProver(server); - -function PermanentProver(server) { - - const logger = require('../logger')('permprover'); - const that = this; - - let blockchainChangedResolver = null, - promiseOfWaitingBetween2BlocksOfOurs = null, - lastComputedBlock = null; - - // Promises triggering the prooving lopp - let resolveContinuePromise = null; - let continuePromise = new Promise((resolve) => resolveContinuePromise = resolve); - - this.allowedToStart = () => { - resolveContinuePromise(true); - }; - - this.loops = 0; - - /****************** - * Main proof loop - *****************/ - co(function*() { - while (yield continuePromise) { - try { - const waitingRaces = []; - - // By default, we do not make a new proof - let doProof = false; - - try { - const selfPubkey = server.keyPair.publicKey; - const dal = server.dal; - const conf = server.conf; - if (!selfPubkey) { - throw 'No self pubkey found.'; - } - let current; - const isMember = yield dal.isMember(selfPubkey); - if (!isMember) { - throw 'Local node is not a member. Waiting to be a member before computing a block.'; - } - current = yield dal.getCurrentBlockOrNull(); - if (!current) { - throw 'Waiting for a root block before computing new blocks'; - } - const trial = yield server.getBcContext().getIssuerPersonalizedDifficulty(selfPubkey); - checkTrialIsNotTooHigh(trial, current, selfPubkey); - const lastIssuedByUs = current.issuer == selfPubkey; - if (lastIssuedByUs && !promiseOfWaitingBetween2BlocksOfOurs) { - promiseOfWaitingBetween2BlocksOfOurs = new Promise((resolve) => setTimeout(resolve, conf.powDelay)); - logger.warn('Waiting ' + conf.powDelay + 'ms before starting to compute next block...'); - } else { - // We have waited enough - promiseOfWaitingBetween2BlocksOfOurs = null; - // But under some conditions, we can make one - doProof = true; - } - } catch (e) { - logger.warn(e); - } - - if (doProof) { - - /******************* - * COMPUTING A BLOCK - ******************/ - yield Promise.race([ - - // We still listen at eventual blockchain change - co(function*() { - // If the blockchain changes - yield new Promise((resolve) => blockchainChangedResolver = resolve); - // Then cancel the generation - yield server.BlockchainService.prover.cancel(); - }), - - // The generation - co(function*() { - try { - const current = yield server.dal.getCurrentBlockOrNull(); - const selfPubkey = server.keyPair.publicKey; - const block2 = yield server.BlockchainService.generateNext(); - const trial2 = yield server.getBcContext().getIssuerPersonalizedDifficulty(selfPubkey); - checkTrialIsNotTooHigh(trial2, current, selfPubkey); - lastComputedBlock = yield server.BlockchainService.makeNextBlock(block2, trial2); - try { - const obj = parsers.parseBlock.syncWrite(dos2unix(lastComputedBlock.getRawSigned())); - yield server.singleWritePromise(obj); - } catch (err) { - logger.warn('Proof-of-work self-submission: %s', err.message || err); - } - } catch (e) { - logger.warn('The proof-of-work generation was canceled: %s', (e && e.message) || e || 'unkonwn reason'); - } - }) - ]); - } else { - - /******************* - * OR WAITING PHASE - ******************/ - if (promiseOfWaitingBetween2BlocksOfOurs) { - waitingRaces.push(promiseOfWaitingBetween2BlocksOfOurs); - } - - let raceDone = false; - - yield Promise.race(waitingRaces.concat([ - - // The blockchain has changed! We or someone else found a proof, we must make a gnu one - new Promise((resolve) => blockchainChangedResolver = () => { - logger.warn('Blockchain changed!'); - resolve(); - }), - - // Security: if nothing happens for a while, trigger the whole process again - new Promise((resolve) => setTimeout(() => { - if (!raceDone) { - logger.warn('Security trigger: proof-of-work process seems stuck'); - resolve(); - } - }, constants.POW_SECURITY_RETRY_DELAY)) - ])); - - raceDone = true; - } - } catch (e) { - logger.warn(e); - } - - that.loops++; - // Informative variable - logger.trace('PoW loops = %s', that.loops); - } - }); - - this.blockchainChanged = (gottenBlock) => co(function*() { - if (server && (!gottenBlock || !lastComputedBlock || gottenBlock.hash !== lastComputedBlock.hash)) { - // Cancel any processing proof - yield server.BlockchainService.prover.cancel(gottenBlock); - // If we were waiting, stop it and process the continuous generation - blockchainChangedResolver && blockchainChangedResolver(); - } - }); - - this.stopEveryting = () => co(function*() { - // First: avoid continuing the main loop - continuePromise = new Promise((resolve) => resolveContinuePromise = resolve); - // Second: stop any started proof - yield server.BlockchainService.prover.cancel(); - // If we were waiting, stop it and process the continuous generation - blockchainChangedResolver && blockchainChangedResolver(); - }); - - function checkTrialIsNotTooHigh(trial, current, selfPubkey) { - if (trial > (current.powMin + constants.POW_MAXIMUM_ACCEPTABLE_HANDICAP)) { - logger.debug('Trial = %s, powMin = %s, pubkey = %s', trial, current.powMin, selfPubkey.slice(0, 6)); - throw 'Too high difficulty: waiting for other members to write next block'; - } - } -} - diff --git a/app/lib/constants.js b/app/lib/constants.js index f9268c12fcb1b1d10343df8abd97b986a1500dde..e709036809764947105cf1b5a40a33eb6314b3d8 100644 --- a/app/lib/constants.js +++ b/app/lib/constants.js @@ -233,7 +233,6 @@ module.exports = { } }, PROOF_OF_WORK: { - MINIMAL_TO_SHOW: 2, MINIMAL_TO_SHOW_IN_LOGS: 3, EVALUATION: 1000, UPPER_BOUND: [ @@ -256,7 +255,6 @@ module.exports = { ] }, - DEFAULT_CPU: 0.6, DEFAULT_CURRENCY_NAME: "no_currency", CONTRACT: { @@ -312,14 +310,9 @@ module.exports = { ENGINE_IDLE_INTERVAL: 5000, - // When to trigger the PoW process again if no PoW is triggered for a while. In milliseconds. - POW_SECURITY_RETRY_DELAY: 10 * 60 * 1000, - POW_DIFFICULTY_RANGE_RATIO: 1.189, TRANSACTION_MAX_TRIES: 10, - NONCE_RANGE: 1000 * 1000 * 1000 * 100, - POW_MAXIMUM_ACCEPTABLE_HANDICAP: 64, ACCOUNT_MINIMUM_CURRENT_BASED_AMOUNT: 100, diff --git a/app/lib/crypto/base58.js b/app/lib/crypto/base58.js deleted file mode 100644 index acfeef7d038e601fdda6719077b1bf9f954bd664..0000000000000000000000000000000000000000 --- a/app/lib/crypto/base58.js +++ /dev/null @@ -1,78 +0,0 @@ -// Base58 encoding/decoding -// Originally written by Mike Hearn for BitcoinJ -// Copyright (c) 2011 Google Inc -// Ported to JavaScript by Stefan Thomas -// Merged Buffer refactorings from base58-native by Stephen Pair -// Copyright (c) 2013 BitPay Inc - -"use strict"; - -let Base58 = {} - -Base58.alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' -Base58.alphabetMap = {} - -for(let i = 0; i < Base58.alphabet.length; i++) { - Base58.alphabetMap[Base58.alphabet.charAt(i)] = i -} - -Base58.encode = function(buffer) { - if (buffer.length === 0) return '' - - let i, j, digits = [0] - for (i = 0; i < buffer.length; i++) { - for (j = 0; j < digits.length; j++) digits[j] <<= 8 - digits[digits.length - 1] += buffer[i] - - let carry = 0 - for (j = digits.length - 1; j >= 0; j--){ - digits[j] += carry - carry = (digits[j] / 58) | 0 - digits[j] %= 58 - } - - while (carry) { - digits.unshift(carry) - carry = (digits[0] / 58) | 0 - digits[0] %= 58 - } - } - - // deal with leading zeros - for (i = 0; i < buffer.length - 1 && buffer[i] == 0; i++) digits.unshift(0) - - return digits.map(function(digit) { return Base58.alphabet[digit] }).join('') -} - -Base58.decode = function(string) { - if (string.length === 0) return (new Uint8Array()) - - let input = string.split('').map(function(c){ - return Base58.alphabetMap[c] - }) - - let i, j, bytes = [0] - for (i = 0; i < input.length; i++) { - for (j = 0; j < bytes.length; j++) bytes[j] *= 58 - bytes[bytes.length - 1] += input[i] - - let carry = 0 - for (j = bytes.length - 1; j >= 0; j--){ - bytes[j] += carry - carry = bytes[j] >> 8 - bytes[j] &= 0xff - } - - while (carry) { - bytes.unshift(carry) - carry = bytes[0] >> 8 - bytes[0] &= 0xff - } - } - - // deal with leading zeros - for (i = 0; i < input.length - 1 && input[i] == 0; i++) bytes.unshift(0) - return (new Uint8Array(bytes)) -} - -module.exports = Base58; diff --git a/app/lib/crypto/base64.js b/app/lib/crypto/base64.js deleted file mode 100644 index dd9e765e1b6fbef7f0374c0a5c79c1cef60daead..0000000000000000000000000000000000000000 --- a/app/lib/crypto/base64.js +++ /dev/null @@ -1,103 +0,0 @@ -/* OpenPGP radix-64/base64 string encoding/decoding - * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de - * version 1.0, check www.haneWIN.de for the latest version - * - * This software is provided as-is, without express or implied warranty. - * Permission to use, copy, modify, distribute or sell this software, with or - * without fee, for any purpose and by any individual or organization, is hereby - * granted, provided that the above copyright notice and this paragraph appear - * in all copies. Distribution as a part of an application or binary must - * include the above copyright notice in the documentation and/or other materials - * provided with the application or distribution. - */ - -"use strict"; - -/** - * @module encoding/base64 - */ - -let b64s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - -/** - * Convert binary string to radix-64 - * @param {String} t binary string to convert - * @returns {string} radix-64 version of input string - * @static - */ -function s2r(t) { - let a, c, n; - let r = '', - l = 0, - s = 0; - let tl = t.length; - - for (n = 0; n < tl; n++) { - c = t.charCodeAt(n); - if (s === 0) { - r += b64s.charAt((c >> 2) & 63); - a = (c & 3) << 4; - } else if (s == 1) { - r += b64s.charAt((a | (c >> 4) & 15)); - a = (c & 15) << 2; - } else if (s == 2) { - r += b64s.charAt(a | ((c >> 6) & 3)); - l += 1; - if ((l % 60) === 0) - r += "\n"; - r += b64s.charAt(c & 63); - } - l += 1; - if ((l % 60) === 0) - r += "\n"; - - s += 1; - if (s == 3) - s = 0; - } - if (s > 0) { - r += b64s.charAt(a); - l += 1; - if ((l % 60) === 0) - r += "\n"; - r += '='; - l += 1; - } - if (s == 1) { - if ((l % 60) === 0) - r += "\n"; - r += '='; - } - - return r; -} - -/** - * Convert radix-64 to binary string - * @param {String} t radix-64 string to convert - * @returns {string} binary version of input string - * @static - */ -function r2s(t) { - let c, n; - let r = '', - s = 0, - a = 0; - let tl = t.length; - - for (n = 0; n < tl; n++) { - c = b64s.indexOf(t.charAt(n)); - if (c >= 0) { - if (s) - r += String.fromCharCode(a | (c >> (6 - s)) & 255); - s = (s + 2) & 7; - a = (c << s) & 255; - } - } - return r; -} - -module.exports = { - encode: s2r, - decode: r2s -}; diff --git a/app/lib/crypto/keyring.js b/app/lib/crypto/keyring.js deleted file mode 100644 index 070af5cb5fadd83a58a2b4c8a9c0a301e2642a86..0000000000000000000000000000000000000000 --- a/app/lib/crypto/keyring.js +++ /dev/null @@ -1,61 +0,0 @@ -"use strict"; -const nacl = require('tweetnacl'); -const base58 = require('./base58'); -const naclBinding = require('naclb'); - -nacl.util = require('./nacl-util'); - -const crypto_sign_BYTES = 64; - -/** - * Verify a signature against data & public key. - * Return true of false as callback argument. - */ -function verify(rawMsg, rawSig, rawPub) { - const msg = nacl.util.decodeUTF8(rawMsg); - const sig = nacl.util.decodeBase64(rawSig); - const pub = base58.decode(rawPub); - const m = new Uint8Array(crypto_sign_BYTES + msg.length); - const sm = new Uint8Array(crypto_sign_BYTES + msg.length); - let i; - for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; - for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; - - // Call to verification lib... - return naclBinding.verify(m, sm, pub); -} - -function Key(pub, sec) { - /***************************** - * - * GENERAL CRYPTO - * - *****************************/ - - this.publicKey = pub; - this.secretKey = sec; - - const rawSec = () => base58.decode(this.secretKey); - - this.json = () => { return { - pub: this.publicKey, - sec: this.secretKey - }}; - - this.sign = (msg) => Promise.resolve(this.signSync(msg)); - - this.signSync = (msg) => { - const m = nacl.util.decodeUTF8(msg); - const signedMsg = naclBinding.sign(m, rawSec()); - const sig = new Uint8Array(crypto_sign_BYTES); - for (let i = 0; i < sig.length; i++) { - sig[i] = signedMsg[i]; - } - return nacl.util.encodeBase64(sig); - }; -} - -module.exports ={ - Key: (pub, sec) => new Key(pub, sec), - verify: verify -}; diff --git a/app/lib/crypto/nacl-util.js b/app/lib/crypto/nacl-util.js deleted file mode 100644 index 05cebc0f408ea69106c6a1f7994976c353f936a7..0000000000000000000000000000000000000000 --- a/app/lib/crypto/nacl-util.js +++ /dev/null @@ -1,50 +0,0 @@ -// Written in 2014-2016 by Dmitry Chestnykh and Devi Mandiri. -// Public domain. -(function(root, f) { - 'use strict'; - if (typeof module !== 'undefined' && module.exports) module.exports = f(); - else if (root.nacl) root.nacl.util = f(); - else { - root.nacl = {}; - root.nacl.util = f(); - } -}(this, function() { - 'use strict'; - - let util = {}; - - util.decodeUTF8 = function(s) { - let i, d = unescape(encodeURIComponent(s)), b = new Uint8Array(d.length); - for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i); - return b; - }; - - util.encodeUTF8 = function(arr) { - let i, s = []; - for (i = 0; i < arr.length; i++) s.push(String.fromCharCode(arr[i])); - return decodeURIComponent(escape(s.join(''))); - }; - - util.encodeBase64 = function(arr) { - if (typeof btoa === 'undefined' || !window) { - return (new Buffer(arr)).toString('base64'); - } else { - let i, s = [], len = arr.length; - for (i = 0; i < len; i++) s.push(String.fromCharCode(arr[i])); - return btoa(s.join('')); - } - }; - - util.decodeBase64 = function(s) { - if (typeof atob === 'undefined' || !window) { - return new Uint8Array(Array.prototype.slice.call(new Buffer(s, 'base64'), 0)); - } else { - let i, d = atob(s), b = new Uint8Array(d.length); - for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i); - return b; - } - }; - - return util; - -})); diff --git a/app/lib/dup/indexer.js b/app/lib/dup/indexer.js index da579a8a7961e690bb1c725caa55461da616740f..70a67b4314b412824d0f658f9d015a7d00058513 100644 --- a/app/lib/dup/indexer.js +++ b/app/lib/dup/indexer.js @@ -3,9 +3,9 @@ const co = require('co'); const _ = require('underscore'); const constants = require('../constants'); -const rawer = require('../ucp/rawer'); +const rawer = require('duniter-common').rawer; const unlock = require('../ucp/txunlock'); -const keyring = require('../crypto/keyring'); +const keyring = require('duniter-common').keyring; const Block = require('../entity/block'); const Identity = require('../entity/identity'); const Certification = require('../entity/certification'); diff --git a/app/lib/entity/block.js b/app/lib/entity/block.js index d25478df7d93f535fb171e7e8275be324f23c191..01463aa0c85f8d13c84957be09713eee2d3cbf93 100644 --- a/app/lib/entity/block.js +++ b/app/lib/entity/block.js @@ -1,6 +1,6 @@ "use strict"; const _ = require('underscore'); -const hashf = require('../ucp/hashf'); +const hashf = require('duniter-common').hashf; const Transaction = require('./transaction'); module.exports = Block; @@ -125,23 +125,23 @@ function Block(json) { }; this.getRawInnerPart = () => { - return require('../ucp/rawer').getBlockInnerPart(this); + return require('duniter-common').rawer.getBlockInnerPart(this); }; this.getRaw = () => { - return require('../ucp/rawer').getBlockWithInnerHashAndNonce(this); + return require('duniter-common').rawer.getBlockWithInnerHashAndNonce(this); }; this.getSignedPart = () => { - return require('../ucp/rawer').getBlockInnerHashAndNonce(this); + return require('duniter-common').rawer.getBlockInnerHashAndNonce(this); }; this.getProofOfWorkPart = () => { - return require('../ucp/rawer').getBlockInnerHashAndNonceWithSignature(this); + return require('duniter-common').rawer.getBlockInnerHashAndNonceWithSignature(this); }; this.getRawSigned = () => { - return require('../ucp/rawer').getBlock(this); + return require('duniter-common').rawer.getBlock(this); }; this.quickDescription = () => { diff --git a/app/lib/entity/certification.js b/app/lib/entity/certification.js index d724ce91acc1fa84685f422678659ebf5ead7573..6461b44d39e2f140cb7498f90b26021a3e166ee6 100644 --- a/app/lib/entity/certification.js +++ b/app/lib/entity/certification.js @@ -1,7 +1,7 @@ "use strict"; const _ = require('underscore'); -const rawer = require('../ucp/rawer'); -const ucp = require('../ucp/buid'); +const rawer = require('duniter-common').rawer; +const ucp = require('duniter-common').buid; const Certification = function(json) { diff --git a/app/lib/entity/configuration.js b/app/lib/entity/configuration.js index 5749d9377759884f70895b984d821a4ba5769060..331342371dad7d4e6839306adfd6077d99cbf842 100644 --- a/app/lib/entity/configuration.js +++ b/app/lib/entity/configuration.js @@ -7,7 +7,6 @@ const defaultConf = function() { "currency": null, "endpoints": [], "rmEndpoints": [], - "cpu": constants.DEFAULT_CPU, "upInterval": 3600 * 1000, "c": constants.CONTRACT.DEFAULT.C, "dt": constants.CONTRACT.DEFAULT.DT, diff --git a/app/lib/entity/identity.js b/app/lib/entity/identity.js index d02c23ea3b19373508b5e93cf03ff8a2f979281c..f4cdc9499387bae65964530238484717d5cd3840 100644 --- a/app/lib/entity/identity.js +++ b/app/lib/entity/identity.js @@ -1,7 +1,7 @@ "use strict"; const _ = require('underscore'); -const hashf = require('../ucp/hashf'); -const rawer = require('../ucp/rawer'); +const hashf = require('duniter-common').hashf; +const rawer = require('duniter-common').rawer; const Identity = function(json) { diff --git a/app/lib/entity/membership.js b/app/lib/entity/membership.js index 95e960b20ab032702287a65b55cd80a21632f34b..92167fc66cee519fc77ff62f27e4eaf96c761f53 100644 --- a/app/lib/entity/membership.js +++ b/app/lib/entity/membership.js @@ -1,7 +1,7 @@ "use strict"; const _ = require('underscore'); const moment = require('moment'); -const rawer = require('../ucp/rawer'); +const rawer = require('duniter-common').rawer; const constants = require('../constants'); const Membership = function(json) { diff --git a/app/lib/entity/peer.js b/app/lib/entity/peer.js index faea69aa9dc9fde2b17e5bccc181e20cc71cb7cf..8cc54e1a76a66bd0322ba492b7dab1b9ffa4f6cc 100644 --- a/app/lib/entity/peer.js +++ b/app/lib/entity/peer.js @@ -1,7 +1,7 @@ "use strict"; const _ = require('underscore'); const contacter = require('duniter-crawler').duniter.methods.contacter; -const rawer = require('../ucp/rawer'); +const rawer = require('duniter-common').rawer; const constants = require('../constants'); module.exports = Peer; diff --git a/app/lib/entity/revocation.js b/app/lib/entity/revocation.js index e3c54fed10dcd64ec23ebc8329d9a5419f9f2cf0..b3acbfd801c6de80f32f521c850309f13cc0b606 100644 --- a/app/lib/entity/revocation.js +++ b/app/lib/entity/revocation.js @@ -1,6 +1,6 @@ "use strict"; const _ = require('underscore'); -const rawer = require('../ucp/rawer'); +const rawer = require('duniter-common').rawer; const Identity = require('./identity'); const Revocation = function(json) { diff --git a/app/lib/entity/transaction.js b/app/lib/entity/transaction.js index 32458ec4d30eadd452b495a9dbadcec3499e556d..91a2baa92844ea2059dfd5fbbd3ee32d731cc6f4 100644 --- a/app/lib/entity/transaction.js +++ b/app/lib/entity/transaction.js @@ -1,7 +1,7 @@ "use strict"; let _ = require('underscore'); -let rawer = require('../ucp/rawer'); -let hashf = require('../ucp/hashf'); +let rawer = require('duniter-common').rawer; +let hashf = require('duniter-common').hashf; let Transaction = function(obj, currency) { diff --git a/app/lib/pow/engine.js b/app/lib/pow/engine.js deleted file mode 100644 index 0bcbb0f3fee49e074961e960632018726d0e2abe..0000000000000000000000000000000000000000 --- a/app/lib/pow/engine.js +++ /dev/null @@ -1,99 +0,0 @@ -"use strict"; - -const childProcess = require('child_process'); -const path = require('path'); -const co = require('co'); -const os = require('os'); -const nuuid = require('node-uuid'); -const querablep = require('querablep'); - -module.exports = function (opts) { - return new PowEngine(opts); -}; - -function PowEngine() { - - const that = this; - - // Super important for Node.js debugging - const debug = process.execArgv.toString().indexOf('--debug') !== -1; - if(debug) { - //Set an unused port number. - process.execArgv = []; - } - - const logger = require('../logger')('engine'); - let powProcess; - let onInfoMessage; - - const exchanges = {}; - - const restart = () => co(function*(){ - if (!powProcess || !powProcess.connected) { - powProcess = childProcess.fork(path.join(__dirname, '.', 'proof.js')); - - powProcess.on('message', function(msg) { - if (!msg.uuid) { - if (onInfoMessage) { - onInfoMessage(msg); - } - } else if (!exchanges[msg.uuid]) { - logger.error('PoW engine has sent a message about an unknown uuid:'); - logger.debug(msg); - } else if (exchanges[msg.uuid].isFulfilled()) { - logger.error('PoW engine has sent a message about an already fulfilled uuid:'); - logger.debug(msg); - } else { - exchanges[msg.uuid].extras.resolve(msg.answer); - } - }); - - powProcess.on('exit', function() { - logger.warn('PoW engine has exited.'); - }); - } - }); - - const ask = (command, value) => co(function*(){ - // Restart the engine as it regularly closes itself if not used (free memory + cpu) - yield restart(); - const uuid = nuuid.v4(); - let resolve, reject; - exchanges[uuid] = querablep(new Promise((res, rej) => { - resolve = res; - reject = rej; - })); - exchanges[uuid].extras = { resolve, reject }; - // Send the message - powProcess.send({ command, uuid, value }); - // Wait for the answer - return exchanges[uuid]; - }); - - this.prove = (block, nonceBeginning, zeros, highMark, pair, forcedTime, medianTimeBlocks, avgGenTime, cpu, prefix) => { - if (os.arch().match(/arm/)) { - cpu /= 2; // Don't know exactly why is ARM so much saturated by PoW, so let's divide by 2 - } - return ask('newPoW', { block, nonceBeginning, zeros, highMark, pair, forcedTime, conf: { medianTimeBlocks, avgGenTime, cpu, prefix } }); - }; - - this.status = () => ask('state'); - - this.cancel = () => co(function*() { - if (that.isConnected()) { - return ask('cancel'); - } - }); - - this.getValue = (key) => ask(key); - - this.setValue = (key, value) => co(function*() { - if (that.isConnected()) { - return ask(key, value); - } - }); - - this.isConnected = () => powProcess ? powProcess.connected : false; - - this.setOnInfoMessage = (callback) => onInfoMessage = callback; -} diff --git a/app/lib/pow/proof.js b/app/lib/pow/proof.js deleted file mode 100644 index 026f8243d8d1b6f6771f8fa8e924b287398d4319..0000000000000000000000000000000000000000 --- a/app/lib/pow/proof.js +++ /dev/null @@ -1,270 +0,0 @@ -"use strict"; -const co = require('co'); -const moment = require('moment'); -const hashf = require('./../ucp/hashf'); -const dos2unix = require('./../system/dos2unix'); -const querablep = require('querablep'); -const rules = require('./../rules/index'); -const constants = require('./../constants'); -const keyring = require('./../crypto/keyring'); -const rawer = require('./../ucp/rawer'); - -let AUTOKILL_TIMEOUT_DELAY = 10 * 1000; -const TURN_DURATION_IN_MILLISEC = 1000; -const PAUSES_PER_TURN = 5; - -let timeoutAutoKill = null; -let computing = querablep(Promise.resolve(null)); -let askedStop = false; - -// By default, we do not prefix the PoW by any number -let prefix = 0; - -let signatureFunc, id, lastPub, lastSecret, currentCPU = 1; - -process.on('uncaughtException', (err) => { - console.error(err.stack || Error(err)); - process.send({error: err}); -}); - -autoKillIfNoContact(); - -process.on('message', (message) => co(function*() { - - switch (message.command) { - - case 'state': - answer(message, computing.isFulfilled() ? 'ready' : 'computing'); - break; - - case 'autokillTimeout': - AUTOKILL_TIMEOUT_DELAY = message.value; - answer(message, 'OK'); - break; - - case 'identify': - lastPub = message.value.pubkey; - id = message.value.identifier; - answer(message, 'OK'); - break; - - case 'pubkey': answer(message, lastPub); break; - case 'id': answer(message, id); break; - case 'cpu': answer(message, currentCPU); break; - case 'prefix': answer(message, prefix); break; - - case 'newPoW': - co(function*() { - yield computing; - const res = yield beginNewProofOfWork(message.value); - answer(message, res); - }); - break; - - case 'cancel': - if (computing.isFulfilled()) { - answer(message, 'ready'); - } else { - askedStop = true; - answer(message, 'cancelling'); - } - break; - - case 'conf': - if (message.value.cpu !== undefined) { - currentCPU = message.value.cpu; - } - if (message.value.prefix !== undefined) { - prefix = parseInt(message.value.prefix) * 10 * constants.NONCE_RANGE; - } - answer(message, { currentCPU, prefix }); - break; - } - - // We received a message, we postpone the autokill protection trigger - autoKillIfNoContact(); - -})); - -function beginNewProofOfWork(stuff) { - askedStop = false; - computing = querablep(co(function*() { - pSend({ powStatus: 'started block#' + stuff.block.number }); - let nonce = 0; - let foundBlock = null; - const conf = stuff.conf; - const block = stuff.block; - const nonceBeginning = stuff.nonceBeginning; - const nbZeros = stuff.zeros; - const pair = stuff.pair; - const forcedTime = stuff.forcedTime; - currentCPU = conf.cpu || constants.DEFAULT_CPU; - prefix = parseInt(conf.prefix || prefix) * 10 * constants.NONCE_RANGE; - const highMark = stuff.highMark; - let sigFunc = null; - if (signatureFunc && lastSecret == pair.sec) { - sigFunc = signatureFunc; - } - else { - lastSecret = pair.sec; - lastPub = pair.pub; - sigFunc = keyring.Key(pair.pub, pair.sec).signSync; - } - signatureFunc = sigFunc; - let pow = "", sig = "", raw = ""; - - block.time = getBlockTime(block, conf, forcedTime); - - // Really start now - let testsCount = 0; - if (nbZeros == 0) { - block.time = block.medianTime; - } - // Compute block's hash - block.inner_hash = getBlockInnerHash(block); - let found = false; - let score = 0; - let turn = 0; - while (!found && !askedStop) { - - // We make a bunch of tests every second - yield Promise.race([ - countDown(TURN_DURATION_IN_MILLISEC), - co(function*() { - try { - - /***** - * A NEW TURN - */ - // Prove - let i = 0; - const thisTurn = turn; - const pausePeriod = score ? score / PAUSES_PER_TURN : 10; // number of pauses per turn - // We limit the number of t - const testsPerRound = score ? Math.floor(score * currentCPU) : 1000 * 1000 * 1000; - // Time is updated regularly during the proof - block.time = getBlockTime(block, conf, forcedTime); - if (block.number == 0) { - block.medianTime = block.time; - } - block.inner_hash = getBlockInnerHash(block); - while(!found && i < testsPerRound && thisTurn == turn && !askedStop) { - nonce++; - // The final nonce is composed of 3 parts - block.nonce = prefix + nonceBeginning + nonce; - raw = dos2unix("InnerHash: " + block.inner_hash + "\nNonce: " + block.nonce + "\n"); - sig = dos2unix(sigFunc(raw)); - pow = hashf("InnerHash: " + block.inner_hash + "\nNonce: " + block.nonce + "\n" + sig + "\n").toUpperCase(); - let j = 0, charOK = true; - while (j < nbZeros && charOK) { - charOK = pow[j] == '0'; - j++; - } - if (charOK) { - found = pow[nbZeros].match(new RegExp('[0-' + highMark + ']')); - } - if (!found && nbZeros > 0 && j - 1 >= constants.PROOF_OF_WORK.MINIMAL_TO_SHOW) { - pSend({ pow: { pow: pow, block: block, nbZeros: nbZeros }}); - } - if (!found) { - i++; - testsCount++; - if (i % pausePeriod == 0) { - yield countDown(0); // Very low pause, just the time to process eventual end of the turn - } - } - } - if (!found) { - if (turn > 0 && !score) { - score = testsCount; - } - // We wait for main "while" countdown to end the turn. This gives of a bit of breath to the CPU (the amount - // of "breath" depends on the "cpu" parameter. - yield countDown(TURN_DURATION_IN_MILLISEC); - } - } catch (e) { - console.error(e); - } - }) - ]); - turn++; - } - block.hash = pow; - block.signature = sig; - if (askedStop) { - askedStop = false; - yield pSend({ pow: { canceled: true }}); - pSend({ powStatus: 'canceled block#' + block.number }); - pSend({ powStatus: 'ready' }); - } else { - foundBlock = { - pow: { - block: block, - testsCount: testsCount, - pow: pow - } - }; - pSend({ powStatus: 'found' }); - } - return foundBlock; - })); - return computing; -} - -function countDown(duration) { - return new Promise((resolve) => setTimeout(resolve, duration)); -} - -function getBlockInnerHash(block) { - const raw = rawer.getBlockInnerPart(block); - return hash(raw); -} - -function hash(str) { - return hashf(str).toUpperCase(); -} - -function getBlockTime (block, conf, forcedTime) { - if (forcedTime) { - return forcedTime; - } - const now = moment.utc().unix(); - const maxAcceleration = rules.HELPERS.maxAcceleration(block, conf); - const timeoffset = block.number >= conf.medianTimeBlocks ? 0 : conf.rootoffset || 0; - const medianTime = block.medianTime; - const upperBound = block.number == 0 ? medianTime : Math.min(medianTime + maxAcceleration, now - timeoffset); - return Math.max(medianTime, upperBound); -} - -function answer(message, answer) { - return new Promise(function (resolve, reject) { - process.send({ - uuid: message.uuid, - answer, - pubkey: lastPub - }, function (error) { - !error && resolve(); - error && reject(); - }); - }); -} - -function pSend(stuff) { - stuff.pubkey = lastPub; - return new Promise(function (resolve, reject) { - process.send(stuff, function (error) { - !error && resolve(); - error && reject(); - }); - }); -} - -function autoKillIfNoContact() { - if (timeoutAutoKill) { - clearTimeout(timeoutAutoKill); - } - // If the timeout is not cleared in some way, the process exits - timeoutAutoKill = setTimeout(() => { - process.exit(); - }, AUTOKILL_TIMEOUT_DELAY); -} diff --git a/app/lib/rules/global_rules.js b/app/lib/rules/global_rules.js index a067bdd6cc728500965c7accd88ac3b0972d06c0..4dc3c55eb7caadb801ba3b72cfe100ae854167aa 100644 --- a/app/lib/rules/global_rules.js +++ b/app/lib/rules/global_rules.js @@ -4,8 +4,8 @@ const Q = require('q'); const co = require('co'); const _ = require('underscore'); const constants = require('../constants'); -const keyring = require('../crypto/keyring'); -const rawer = require('../ucp/rawer'); +const keyring = require('duniter-common').keyring; +const rawer = require('duniter-common').rawer; const indexer = require('../dup/indexer'); const Identity = require('../entity/identity'); const Transaction = require('../entity/transaction'); diff --git a/app/lib/rules/local_rules.js b/app/lib/rules/local_rules.js index b713db8550c40096b0edcfcbe6fab299ed8cb250..779c64400d4d1916933f4beab7f3d835fac0ad22 100644 --- a/app/lib/rules/local_rules.js +++ b/app/lib/rules/local_rules.js @@ -4,12 +4,13 @@ const co = require('co'); const _ = require('underscore'); const constants = require('../constants'); const indexer = require('../dup/indexer'); -const hashf = require('../ucp/hashf'); -const keyring = require('../crypto/keyring'); -const rawer = require('../ucp/rawer'); +const hashf = require('duniter-common').hashf; +const keyring = require('duniter-common').keyring; +const rawer = require('duniter-common').rawer; const Identity = require('../entity/identity'); const Membership = require('../entity/membership'); const Transaction = require('../entity/transaction'); +const maxAcceleration = require('duniter-common').rules.HELPERS.maxAcceleration; let rules = {}; @@ -79,8 +80,8 @@ rules.FUNCTIONS = { checkBlockTimes: (block, conf) => co(function *() { const time = parseInt(block.time); const medianTime = parseInt(block.medianTime); - if (block.number > 0 && (time < medianTime || time > medianTime + maxAcceleration(block, conf))) - throw Error('A block must have its Time between MedianTime and MedianTime + ' + maxAcceleration(block, conf)); + if (block.number > 0 && (time < medianTime || time > medianTime + maxAcceleration(conf))) + throw Error('A block must have its Time between MedianTime and MedianTime + ' + maxAcceleration(conf)); else if (block.number == 0 && time != medianTime) throw Error('Root block must have Time equal MedianTime'); return true; @@ -370,11 +371,6 @@ rules.FUNCTIONS = { }) }; -function maxAcceleration (block, conf) { - let maxGenTime = Math.ceil(conf.avgGenTime * constants.POW_DIFFICULTY_RANGE_RATIO); - return Math.ceil(maxGenTime * conf.medianTimeBlocks); -} - function checkSingleMembershipSignature(ms) { return keyring.verify(ms.getRaw(), ms.signature, ms.issuer); } @@ -431,7 +427,7 @@ function checkBunchOfTransactions(txs, done){ rules.HELPERS = { - maxAcceleration: maxAcceleration, + maxAcceleration: (block, conf) => maxAcceleration(conf), checkSingleMembershipSignature: checkSingleMembershipSignature, diff --git a/app/lib/streams/parsers/GenericParser.js b/app/lib/streams/parsers/GenericParser.js index b0768144b079d6ce75198a2222564c74f4c5b40b..753752e7d8bcc8ae1fc4d9286d83c9366ed9d754 100644 --- a/app/lib/streams/parsers/GenericParser.js +++ b/app/lib/streams/parsers/GenericParser.js @@ -1,7 +1,7 @@ "use strict"; const util = require('util'); const stream = require('stream'); -const hashf = require('../../ucp/hashf'); +const hashf = require('duniter-common').hashf; const logger = require('../../logger')('gen_parser'); const constants = require('../../constants'); diff --git a/app/lib/streams/parsers/block.js b/app/lib/streams/parsers/block.js index d7c5366e321656b46dfb86f4c8b55ac01dbde060..58368da34851b718a45782faaca0d4ae84ae510b 100644 --- a/app/lib/streams/parsers/block.js +++ b/app/lib/streams/parsers/block.js @@ -2,8 +2,8 @@ const util = require('util'); const GenericParser = require('./GenericParser'); const Block = require('../../entity/block'); -const hashf = require('../../ucp/hashf'); -const rawer = require('../../ucp/rawer'); +const hashf = require('duniter-common').hashf; +const rawer = require('duniter-common').rawer; const constants = require('../../constants'); module.exports = BlockParser; @@ -54,7 +54,7 @@ function BlockParser (onError) { obj.transactions = obj.transactions || []; obj.version = obj.version || ''; obj.type = obj.type || ''; - obj.hash = hashf(require('../../ucp/rawer').getBlockInnerHashAndNonceWithSignature(obj)).toUpperCase(); + obj.hash = hashf(require('duniter-common').rawer.getBlockInnerHashAndNonceWithSignature(obj)).toUpperCase(); obj.inner_hash = obj.inner_hash || ''; obj.currency = obj.currency || ''; obj.nonce = obj.nonce || ''; diff --git a/app/lib/streams/parsers/certification.js b/app/lib/streams/parsers/certification.js index adebc6e8944c495ba130121d6dfb0e13204c5efe..aa57b0ef41818fe519687777a161d75a7f4ac766 100644 --- a/app/lib/streams/parsers/certification.js +++ b/app/lib/streams/parsers/certification.js @@ -1,7 +1,7 @@ "use strict"; const GenericParser = require('./GenericParser'); const util = require('util'); -const rawer = require('../../ucp/rawer'); +const rawer = require('duniter-common').rawer; const constants = require('../../constants'); module.exports = CertificationParser; diff --git a/app/lib/streams/parsers/identity.js b/app/lib/streams/parsers/identity.js index 5f405bb3a3472f2f8982dc5fe5e44d77ac8f5f0d..0f79a5d4b364a59017c801cabbca6774f4f88798 100644 --- a/app/lib/streams/parsers/identity.js +++ b/app/lib/streams/parsers/identity.js @@ -1,8 +1,8 @@ "use strict"; const GenericParser = require('./GenericParser'); const util = require('util'); -const rawer = require('../../ucp/rawer'); -const hashf = require('../../ucp/hashf'); +const rawer = require('duniter-common').rawer; +const hashf = require('duniter-common').hashf; const constants = require('../../constants'); module.exports = IdentityParser; diff --git a/app/lib/streams/parsers/membership.js b/app/lib/streams/parsers/membership.js index 19c6ba6cf52bcd8c1c2dddda243e96e0376f4426..a0243c4efff5ec2a4f18ee85f798ee35d442a92a 100644 --- a/app/lib/streams/parsers/membership.js +++ b/app/lib/streams/parsers/membership.js @@ -1,7 +1,7 @@ "use strict"; const GenericParser = require('./GenericParser'); -const ucp = require('../../ucp/buid'); -const rawer = require('../../ucp/rawer'); +const ucp = require('duniter-common').buid; +const rawer = require('duniter-common').rawer; const util = require('util'); const constants = require('../../constants'); diff --git a/app/lib/streams/parsers/peer.js b/app/lib/streams/parsers/peer.js index 66a7437a77861a67c8bc219a3337be5e84e31d6a..64a58436b0276cedf22c61db782d9cf30bddbf0b 100644 --- a/app/lib/streams/parsers/peer.js +++ b/app/lib/streams/parsers/peer.js @@ -1,6 +1,6 @@ "use strict"; const GenericParser = require('./GenericParser'); -const rawer = require('../../ucp/rawer'); +const rawer = require('duniter-common').rawer; const util = require('util'); const constants = require('../../constants'); diff --git a/app/lib/streams/parsers/revocation.js b/app/lib/streams/parsers/revocation.js index 83f8630222591ff56014b708f848cb2b68a2f444..f77544659715501aa0043bb3581e46e6d8505ded 100644 --- a/app/lib/streams/parsers/revocation.js +++ b/app/lib/streams/parsers/revocation.js @@ -1,8 +1,8 @@ "use strict"; const GenericParser = require('./GenericParser'); const util = require('util'); -const rawer = require('../../ucp/rawer'); -const hashf = require('../../ucp/hashf'); +const rawer = require('duniter-common').rawer; +const hashf = require('duniter-common').hashf; const constants = require('../../constants'); module.exports = RevocationParser; diff --git a/app/lib/streams/parsers/transaction.js b/app/lib/streams/parsers/transaction.js index 74d3d1b225a5caf147eb85c1c86ccba3b05d87b3..25da6f462c8f46a8e82e96b78808418fc881ddf5 100644 --- a/app/lib/streams/parsers/transaction.js +++ b/app/lib/streams/parsers/transaction.js @@ -1,6 +1,6 @@ "use strict"; const GenericParser = require('./GenericParser'); -const rawer = require('../../ucp/rawer'); +const rawer = require('duniter-common').rawer; const constants = require('../../constants'); const util = require('util'); diff --git a/app/lib/system/dos2unix.js b/app/lib/system/dos2unix.js deleted file mode 100644 index 32fdce59314af70c76489f3140ba64bf76fd916b..0000000000000000000000000000000000000000 --- a/app/lib/system/dos2unix.js +++ /dev/null @@ -1,23 +0,0 @@ -"use strict"; -const util = require('util'); -const stream = require('stream'); - -module.exports = function (str) { - if (str) - return dos2unix(str); - else - return new Dos2UnixStream(); -}; - -const dos2unix = (str) => str.replace(/\r\n/g, '\n'); - -function Dos2UnixStream () { - stream.Transform.apply(this); - - this._write = function (str, enc, done) { - this.push(dos2unix(str.toString())); - done(); - } -} - -util.inherits(Dos2UnixStream, stream.Transform); diff --git a/app/lib/system/unix2dos.js b/app/lib/system/unix2dos.js index e52b0fadcdf711c22d526210fe7f59af0b655d93..980e2af01b76ed68cdbbb2f28b37b2a597f57bf2 100644 --- a/app/lib/system/unix2dos.js +++ b/app/lib/system/unix2dos.js @@ -1,5 +1,5 @@ "use strict"; -const dos2unix = require('./dos2unix'); +const dos2unix = require('duniter-common').dos2unix; const util = require('util'); const stream = require('stream'); diff --git a/app/lib/ucp/buid.js b/app/lib/ucp/buid.js deleted file mode 100644 index 561ae1687ef534ddb84cc83610a37fdb15063fb0..0000000000000000000000000000000000000000 --- a/app/lib/ucp/buid.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; -const hashf = require('./hashf'); -const constants = require('../constants'); - -const buidFunctions = function(number, hash) { - if (arguments.length === 2) { - return [number, hash].join('-'); - } - if (arguments[0]) { - return [arguments[0].number, arguments[0].hash].join('-'); - } - return '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855'; -}; - -buidFunctions.fromTS = (line) => line.match(/TS:(.*)/)[1]; -buidFunctions.fromIdty = (idty) => this(idty.ts_number, idty.ts_hash); - -module.exports = { - - format: { - - hashf: (value) => hashf(String(value)).toUpperCase(), - - isBuid: (value) => (typeof value === 'string') && value.match(constants.BLOCK_UID) ? true : false, - - buid: buidFunctions, - - obuid: (line) => { - let sp = this.buid.fromTS(line).split('-'); - return { - number: sp[0], - hash: sp[1] - }; - } - } -}; diff --git a/app/lib/ucp/hashf.js b/app/lib/ucp/hashf.js deleted file mode 100644 index f1a1bd2ee50e8f580c866ca2b602c74d796621bc..0000000000000000000000000000000000000000 --- a/app/lib/ucp/hashf.js +++ /dev/null @@ -1,8 +0,0 @@ -"use strict"; - -module.exports = function (str){ - return require("crypto") - .createHash("sha256") - .update(str) - .digest("hex"); -}; diff --git a/app/lib/ucp/rawer.js b/app/lib/ucp/rawer.js deleted file mode 100644 index 34ba78e7f571715e4e31053b9469f00f48abba82..0000000000000000000000000000000000000000 --- a/app/lib/ucp/rawer.js +++ /dev/null @@ -1,228 +0,0 @@ -"use strict"; -let dos2unix = require('../system/dos2unix'); -let constants = require('../constants'); - -module.exports = new function() { - - this.getOfficialIdentity = (json) => { - let raw = ""; - raw += "Version: " + (json.version || constants.DOCUMENTS_VERSION) + "\n"; - raw += "Type: Identity\n"; - raw += "Currency: " + json.currency + "\n"; - raw += "Issuer: " + (json.issuer || json.pubkey) + "\n"; - raw += "UniqueID: " + json.uid + '\n'; - raw += "Timestamp: " + json.buid + '\n'; - if (json.sig) { - raw += json.sig + '\n'; - } - return dos2unix(raw); - }; - - this.getOfficialCertification = (json) => { - let raw = getNormalHeader('Certification', json); - raw += "IdtyIssuer: " + json.idty_issuer + '\n'; - raw += "IdtyUniqueID: " + json.idty_uid + '\n'; - raw += "IdtyTimestamp: " + json.idty_buid + '\n'; - raw += "IdtySignature: " + json.idty_sig + '\n'; - raw += "CertTimestamp: " + json.buid + '\n'; - if (json.sig) { - raw += json.sig + '\n'; - } - return dos2unix(raw); - }; - - this.getOfficialRevocation = (json) => { - let raw = getNormalHeader('Revocation', json); - raw += "IdtyUniqueID: " + json.uid + '\n'; - raw += "IdtyTimestamp: " + json.buid + '\n'; - raw += "IdtySignature: " + json.sig + '\n'; - if (json.revocation) { - raw += json.revocation + '\n'; - } - return dos2unix(raw); - }; - - this.getPeerWithoutSignature = (json) => { - let raw = ""; - raw += "Version: " + (json.version || constants.DOCUMENTS_VERSION) + "\n"; - raw += "Type: Peer\n"; - raw += "Currency: " + json.currency + "\n"; - raw += "PublicKey: " + json.pubkey + "\n"; - raw += "Block: " + json.block + "\n"; - raw += "Endpoints:" + "\n"; - (json.endpoints || []).forEach((ep) => { - raw += ep + "\n"; - }); - return dos2unix(raw); - }; - - this.getPeer = (json) => { - return dos2unix(signed(this.getPeerWithoutSignature(json), json)); - }; - - this.getMembershipWithoutSignature = (json) => { - let raw = getNormalHeader('Membership', json); - raw += "Block: " + json.block + "\n"; - raw += "Membership: " + json.membership + "\n"; - if (json.userid) - raw += "UserID: " + json.userid + "\n"; - if (json.certts) - raw += "CertTS: " + json.certts + "\n"; - return dos2unix(raw); - }; - - this.getMembership = (json) => { - return dos2unix(signed(this.getMembershipWithoutSignature(json), json)); - }; - - this.getBlockInnerPart = (json) => { - let raw = ""; - raw += "Version: " + (json.version || constants.DOCUMENTS_VERSION) + "\n"; - raw += "Type: Block\n"; - raw += "Currency: " + json.currency + "\n"; - raw += "Number: " + json.number + "\n"; - raw += "PoWMin: " + json.powMin + "\n"; - raw += "Time: " + json.time + "\n"; - raw += "MedianTime: " + json.medianTime + "\n"; - if (json.dividend) - raw += "UniversalDividend: " + json.dividend + "\n"; - raw += "UnitBase: " + json.unitbase + "\n"; - raw += "Issuer: " + json.issuer + "\n"; - raw += "IssuersFrame: " + json.issuersFrame + "\n"; - raw += "IssuersFrameVar: " + json.issuersFrameVar + "\n"; - raw += "DifferentIssuersCount: " + json.issuersCount + "\n"; - if(json.previousHash) - raw += "PreviousHash: " + json.previousHash + "\n"; - if(json.previousIssuer) - raw += "PreviousIssuer: " + json.previousIssuer + "\n"; - if(json.parameters) - raw += "Parameters: " + json.parameters + "\n"; - raw += "MembersCount: " + json.membersCount + "\n"; - raw += "Identities:\n"; - for (const idty of (json.identities || [])){ - raw += idty + "\n"; - } - raw += "Joiners:\n"; - for (const joiner of (json.joiners || [])){ - raw += joiner + "\n"; - } - raw += "Actives:\n"; - for (const active of (json.actives || [])){ - raw += active + "\n"; - } - raw += "Leavers:\n"; - for (const leaver of (json.leavers || [])){ - raw += leaver + "\n"; - } - raw += "Revoked:\n"; - for (const revoked of (json.revoked || [])){ - raw += revoked + "\n"; - } - raw += "Excluded:\n"; - for (const excluded of (json.excluded || [])){ - raw += excluded + "\n"; - } - raw += "Certifications:\n"; - for (const cert of (json.certifications || [])){ - raw += cert + "\n"; - } - raw += "Transactions:\n"; - for (const tx of (json.transactions || [])){ - raw += tx.raw || this.getCompactTransaction(tx); - } - return dos2unix(raw); - }; - - this.getBlockWithInnerHashAndNonce = (json) => { - let raw = this.getBlockInnerPart(json); - raw += "InnerHash: " + json.inner_hash + "\n"; - raw += "Nonce: " + json.nonce + "\n"; - return dos2unix(raw); - }; - - this.getBlockInnerHashAndNonce = (json) => { - let raw = "" + - "InnerHash: " + json.inner_hash + "\n" + - "Nonce: " + json.nonce + "\n"; - return dos2unix(raw); - }; - - this.getBlockInnerHashAndNonceWithSignature = (json) => { - let raw = "" + - "InnerHash: " + json.inner_hash + "\n" + - "Nonce: " + json.nonce + "\n"; - return dos2unix(signed(raw, json)); - }; - - this.getBlock = (json) => { - return dos2unix(signed(this.getBlockWithInnerHashAndNonce(json), json)); - }; - - this.getTransaction = (json) => { - let raw = ""; - raw += "Version: " + (json.version) + "\n"; - raw += "Type: Transaction\n"; - raw += "Currency: " + json.currency + "\n"; - raw += "Blockstamp: " + json.blockstamp + "\n"; - raw += "Locktime: " + json.locktime + "\n"; - raw += "Issuers:\n"; - (json.issuers || []).forEach((issuer) => { - raw += issuer + '\n'; - }); - raw += "Inputs:\n"; - (json.inputs || []).forEach((input) => { - raw += input + '\n'; - }); - raw += "Unlocks:\n"; - (json.unlocks || []).forEach((input) => { - raw += input + '\n'; - }); - raw += "Outputs:\n"; - (json.outputs || []).forEach((output) => { - raw += output + '\n'; - }); - raw += "Comment: " + (json.comment || "") + "\n"; - (json.signatures || []).forEach((signature) => { - raw += signature + '\n'; - }); - return dos2unix(raw); - }; - - this.getCompactTransaction = (json) => { - let issuers = json.issuers; - let raw = ["TX", json.version, issuers.length, json.inputs.length, json.unlocks.length, json.outputs.length, json.comment ? 1 : 0, json.locktime || 0].join(':') + '\n'; - raw += json.blockstamp + "\n"; - (issuers || []).forEach((issuer) => { - raw += issuer + '\n'; - }); - (json.inputs || []).forEach((input) => { - raw += input + '\n'; - }); - (json.unlocks || []).forEach((input) => { - raw += input + '\n'; - }); - (json.outputs || []).forEach((output) => { - raw += output + '\n'; - }); - if (json.comment) - raw += json.comment + '\n'; - (json.signatures || []).forEach((signature) => { - raw += signature + '\n'; - }); - return dos2unix(raw); - }; - - let getNormalHeader = (doctype, json) => { - let raw = ""; - raw += "Version: " + (json.version || constants.DOCUMENTS_VERSION) + "\n"; - raw += "Type: " + doctype + "\n"; - raw += "Currency: " + json.currency + "\n"; - raw += "Issuer: " + json.issuer + "\n"; - return raw; - }; - - let signed = (raw, json) => { - raw += json.signature + '\n'; - return raw; - }; -}; diff --git a/app/lib/ucp/txunlock.js b/app/lib/ucp/txunlock.js index 85ed557545728cc551e5f3e8c5021010dd6951bf..beacb2a8525072e9bfa478f501919fb3cd95c16f 100644 --- a/app/lib/ucp/txunlock.js +++ b/app/lib/ucp/txunlock.js @@ -1,7 +1,7 @@ "use strict"; let Parser = require("jison").Parser; -let ucp = require('./buid'); +let ucp = require('duniter-common').buid; let grammar = { "lex": { diff --git a/app/lib/wizard.js b/app/lib/wizard.js index 32fc101d32e716882926e12275be652106d0b1c5..d8255af7ee6ea6f0b53cee24a2eeaad71004f3be 100644 --- a/app/lib/wizard.js +++ b/app/lib/wizard.js @@ -12,16 +12,16 @@ module.exports = function () { function Wizard () { - this.configPoW = function (conf, program, done) { + this.configPoW = function (conf, program, logger, done) { doTasks(['pow'], conf, done); }; - this.configCurrency = function (conf, program, done) { + this.configCurrency = function (conf, program, logger, done) { doTasks(['currency'], conf, done); }; - this.configUCP = function (conf, program, done) { - doTasks(['ucp'], conf, done); + this.configUCP = function (conf, program, logger, done) { + doTasks(['parameters'], conf, done); }; } @@ -52,7 +52,7 @@ const tasks = { ], done); }, - ucp: function (conf, done) { + parameters: function (conf, done) { async.waterfall([ async.apply(simpleFloat, "Universal Dividend %growth", "c", conf), async.apply(simpleInteger, "Universal Dividend period (in seconds)", "dt", conf), diff --git a/app/modules/daemon.js b/app/modules/daemon.js index e87cc9aa1843bb7dbd1b2adedd012fe93509176d..b228bbe34157a06966568bb284eefcb4ed9c9897 100644 --- a/app/modules/daemon.js +++ b/app/modules/daemon.js @@ -5,6 +5,10 @@ const co = require('co'); module.exports = { duniter: { + service: { + process: (server) => ServerService(server) + }, + cli: [{ name: 'start', desc: 'Start Duniter node daemon.', @@ -39,6 +43,12 @@ module.exports = { } }; +function ServerService(server) { + server.startService = () => Promise.resolve(); + server.stopService = () => Promise.resolve(); + return server; +} + function needsToBeLaunchedByScript(logger) { logger.error('This command must not be launched directly, please use duniter.sh script'); } diff --git a/app/modules/gen.js b/app/modules/gen.js deleted file mode 100644 index 99a564d68054b4808d43f7ab2d46f20bfc21844e..0000000000000000000000000000000000000000 --- a/app/modules/gen.js +++ /dev/null @@ -1,135 +0,0 @@ -"use strict"; - -const co = require('co'); -const async = require('async'); -const multicaster = require('../lib/streams/multicaster'); -const Peer = require('../lib/entity/peer'); -const logger = require('../lib/logger')('gen'); - -module.exports = { - - duniter: { - - cliOptions: [ - {value: '--show', desc: 'With gen-next or gen-root commands, displays the generated block.'}, - {value: '--check', desc: 'With gen-next: just check validity of generated block.'} - ], - - cli: [{ - name: 'gen-next [host] [port] [difficulty]', - desc: 'Tries to generate the next block of the blockchain.', - onDatabaseExecute: (server, conf, program, params) => co(function*() { - const host = params[0]; - const port = params[1]; - const difficulty = params[2]; - return generateAndSend(program, host, port, difficulty, server, (server) => server.BlockchainService.generateNext); - }) - }, { - name: 'gen-root [host] [port] [difficulty]', - desc: 'Tries to generate root block, with choice of root members.', - onDatabaseExecute: (server, conf, program, params, startServices, stopServices) => co(function*() { - const host = params[0]; - const port = params[1]; - const difficulty = params[2]; - if (!host) { - throw 'Host is required.'; - } - if (!port) { - throw 'Port is required.'; - } - if (!difficulty) { - throw 'Difficulty is required.'; - } - return generateAndSend(program, host, port, difficulty, server, (server) => server.BlockchainService.generateManualRoot); - }) - }] - } -} - -function generateAndSend(program, host, port, difficulty, server, getGenerationMethod) { - return new Promise((resolve, reject) => { - async.waterfall([ - function (next) { - const method = getGenerationMethod(server); - co(function*(){ - try { - const block = yield method(); - next(null, block); - } catch(e) { - next(e); - } - }); - }, - function (block, next) { - if (program.check) { - block.time = block.medianTime; - program.show && console.log(block.getRawSigned()); - co(function*(){ - try { - yield server.doCheckBlock(block); - logger.info('Acceptable block'); - next(); - } catch (e) { - next(e); - } - }); - } - else { - logger.debug('Block to be sent: %s', block.quickDescription()); - async.waterfall([ - function (next) { - // Extract key pair - co(function*(){ - try { - const pair = yield server.conf.keyPair; - next(null, pair); - } catch(e) { - next(e); - } - }); - }, - function (pair, next) { - proveAndSend(program, server, block, pair.publicKey, parseInt(difficulty), host, parseInt(port), next); - } - ], next); - } - } - ], (err, data) => { - err && reject(err); - !err && resolve(data); - }); - }); -} - -function proveAndSend(program, server, block, issuer, difficulty, host, port, done) { - const BlockchainService = server.BlockchainService; - async.waterfall([ - function (next) { - block.issuer = issuer; - program.show && console.log(block.getRawSigned()); - co(function*(){ - try { - const proven = yield BlockchainService.prove(block, difficulty); - next(null, proven); - } catch(e) { - next(e); - } - }); - }, - function (block, next) { - const peer = new Peer({ - endpoints: [['BASIC_MERKLED_API', host, port].join(' ')] - }); - program.show && console.log(block.getRawSigned()); - logger.info('Posted block ' + block.quickDescription()); - co(function*(){ - try { - yield multicaster(server.conf).sendBlock(peer, block); - next(); - } catch(e) { - next(e); - } - }); - } - ], done); -} diff --git a/app/modules/prover.js b/app/modules/prover.js deleted file mode 100644 index 035831c2dca98f7ed1afdf87de748563bd435a59..0000000000000000000000000000000000000000 --- a/app/modules/prover.js +++ /dev/null @@ -1,44 +0,0 @@ -"use strict"; - -const co = require('co'); -const util = require('util'); -const stream = require('stream'); -const constants = require('../lib/constants'); -const permanentProver = require('../lib/computation/permanentProver'); - -module.exports = { - duniter: { - service: { - output: (server, conf, logger) => new Prover(server, conf, logger) - }, - - methods: { - prover: (server, conf, logger) => new Prover(server, conf, logger) - } - } -} - -function Prover(server) { - - const permaProver = this.permaProver = permanentProver(server); - - stream.Transform.call(this, { objectMode: true }); - - this._write = function (obj, enc, done) { - // Never close the stream - if (obj && obj.membersCount) { - permaProver.blockchainChanged(obj); - } - done && done(); - }; - - this.startService = () => co(function*() { - permaProver.allowedToStart(); - }); - - this.stopService = () => co(function*() { - permaProver.stopEveryting(); - }); -} - -util.inherits(Prover, stream.Transform); diff --git a/app/modules/wizard.js b/app/modules/wizard.js index 51a1420a2e4c7b8fdb1e5636b9c675e9e2da5bd4..c6eb18e829f84f8a6dfe6f7ab66da66c49990299 100644 --- a/app/modules/wizard.js +++ b/app/modules/wizard.js @@ -12,7 +12,7 @@ module.exports = { // The wizard itself also defines its personal tasks 'currency': Q.nbind(wizard().configCurrency, null), 'pow': Q.nbind(wizard().configPoW, null), - 'ucp': Q.nbind(wizard().configUCP, null) + 'parameters': Q.nbind(wizard().configUCP, null) }, cli: [{ @@ -23,6 +23,9 @@ module.exports = { const step = params[0]; const tasks = step ? [wizardTasks[step]] : Object.values(wizardTasks); for (const task of tasks) { + if (!task) { + throw 'Unknown task'; + } yield task(conf, program, server.logger); } // Check config diff --git a/app/service/BlockchainService.js b/app/service/BlockchainService.js index 2e6ed4c41b7a071a3b53766dce9be834f5e7ee4f..22c93ff869fda6637b01b7c910264b09693b3769 100644 --- a/app/service/BlockchainService.js +++ b/app/service/BlockchainService.js @@ -7,8 +7,7 @@ const parsers = require('../lib/streams/parsers'); const rules = require('../lib/rules'); const constants = require('../lib/constants'); const blockchainCtx = require('../lib/computation/blockchainContext'); -const blockGenerator = require('../lib/computation/blockGenerator'); -const blockProver = require('../lib/computation/blockProver'); +const blockGenerator = require('duniter-prover').duniter.methods.blockGenerator; const Block = require('../lib/entity/block'); const Identity = require('../lib/entity/identity'); const Transaction = require('../lib/entity/transaction'); @@ -26,8 +25,6 @@ function BlockchainService (server) { let that = this; const mainContext = blockchainCtx(); - const prover = this.prover = blockProver(server); - const generator = blockGenerator(mainContext, prover); let conf, dal, logger, selfPubkey; this.getContext = () => mainContext; @@ -36,8 +33,6 @@ function BlockchainService (server) { dal = newDAL; conf = newConf; mainContext.setConfDAL(conf, dal); - prover.setConfDAL(conf, dal, newKeyPair); - generator.setConfDAL(conf, dal, newKeyPair); selfPubkey = newKeyPair.publicKey; logger = require('../lib/logger')(dal.profile); }; @@ -250,16 +245,6 @@ function BlockchainService (server) { this.applyNextAvailableFork = () => this.pushFIFO(() => mainContext.applyNextAvailableFork()); - /** - * Generates root block with manual selection of root members. - */ - this.generateManualRoot = () => generator.manualRoot(); - - /** - * Generates next block, finding newcomers, renewers, leavers, certs, transactions, etc. - */ - this.generateNext = (params) => generator.nextBlock(params); - this.requirementsOfIdentities = (identities) => co(function *() { let all = []; let current = yield dal.getCurrentBlockOrNull(); @@ -283,6 +268,7 @@ function BlockchainService (server) { let expiresPending = 0; let certs = []; try { + const generator = blockGenerator(server); const join = yield generator.getSinglePreJoinData(current, idty.hash); const pubkey = join.identity.pubkey; // Check WoT stability @@ -365,13 +351,9 @@ function BlockchainService (server) { return certsFromLinks.concat(certsFromCerts); }); - this.prove = prover.prove; - this.isMember = () => dal.isMember(selfPubkey); this.getCountOfSelfMadePoW = () => dal.getCountOfPoW(selfPubkey); - this.makeNextBlock = generator.makeNextBlock; - this.saveParametersForRootBlock = (block) => co(function *() { let mainFork = mainContext; let rootBlock = block || (yield dal.getBlock(0)); @@ -443,6 +425,4 @@ function BlockchainService (server) { } return dal.getBlocksBetween(from, from + count - 1); }); - - this.changeProverCPUSetting = (cpu) => prover.changeCPU(cpu); } diff --git a/app/service/IdentityService.js b/app/service/IdentityService.js index 4d0d5c7e5f2bc9812c711c78e684bebb2a08775f..6dda990864e3c629a12c1f88eedb47c82809584e 100644 --- a/app/service/IdentityService.js +++ b/app/service/IdentityService.js @@ -1,7 +1,7 @@ "use strict"; const Q = require('q'); const rules = require('../lib/rules'); -const keyring = require('../lib/crypto/keyring'); +const keyring = require('duniter-common').keyring; const constants = require('../lib/constants'); const Block = require('../../app/lib/entity/block'); const Identity = require('../../app/lib/entity/identity'); diff --git a/app/service/MembershipService.js b/app/service/MembershipService.js index 3eb0ccb488da0e550fcc2df9d2c458eada1f3911..a31075bf38513a32be5042250f085674ed60123f 100644 --- a/app/service/MembershipService.js +++ b/app/service/MembershipService.js @@ -2,7 +2,7 @@ const co = require('co'); const rules = require('../lib/rules'); -const hashf = require('../lib/ucp/hashf'); +const hashf = require('duniter-common').hashf; const constants = require('../lib/constants'); const Membership = require('../lib/entity/membership'); const AbstractService = require('./AbstractService'); diff --git a/app/service/PeeringService.js b/app/service/PeeringService.js index c9eacd05670e625a08ee555e0bbe00ebddc7af2d..2f9dd485bc50f88d6691297f35ff5bad06f4c117 100644 --- a/app/service/PeeringService.js +++ b/app/service/PeeringService.js @@ -6,11 +6,11 @@ const Q = require('q'); const events = require('events'); const rp = require('request-promise'); const multicaster = require('../lib/streams/multicaster'); -const keyring = require('../lib/crypto/keyring'); +const keyring = require('duniter-common').keyring; const logger = require('../lib/logger')('peering'); -const dos2unix = require('../lib/system/dos2unix'); -const hashf = require('../lib/ucp/hashf'); -const rawer = require('../lib/ucp/rawer'); +const dos2unix = require('duniter-common').dos2unix; +const hashf = require('duniter-common').hashf; +const rawer = require('duniter-common').rawer; const constants = require('../lib/constants'); const Peer = require('../lib/entity/peer'); const AbstractService = require('./AbstractService'); @@ -128,7 +128,9 @@ function PeeringService(server) { if (!localNodeNotListed) { const indexOfThisNode = peerEntity.endpoints.indexOf(localEndpoint); if (indexOfThisNode !== -1) { - server.BlockchainService.prover.changePoWPrefix((indexOfThisNode + 1) * 10); // We multiply by 10 to give room to computers with < 100 cores + server.push({ + nodeIndexInPeers: indexOfThisNode + }); } else { logger.warn('This node has his interface listed in the peer document, but its index cannot be found.'); } diff --git a/index.js b/index.js index 0bba06f98d01ff59b70461596c7addc484578d89..151cf07d64df3a45e6ab553e8d085cf736fc13ed 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ const Q = require('q'); const co = require('co'); +const es = require('event-stream'); const util = require('util'); const stream = require('stream'); const _ = require('underscore'); @@ -11,10 +12,8 @@ const constants = require('./app/lib/constants'); const wizard = require('./app/lib/wizard'); const logger = require('./app/lib/logger')('duniter'); -const dkeypairDependency = require('duniter-keypair'); const configDependency = require('./app/modules/config'); const wizardDependency = require('./app/modules/wizard'); -const genDependency = require('./app/modules/gen'); const resetDependency = require('./app/modules/reset'); const checkConfDependency = require('./app/modules/check-config'); const exportBcDependency = require('./app/modules/export-bc'); @@ -22,9 +21,7 @@ const reapplyDependency = require('./app/modules/reapply'); const revertDependency = require('./app/modules/revert'); const daemonDependency = require('./app/modules/daemon'); const pSignalDependency = require('./app/modules/peersignal'); -const crawlerDependency = require('duniter-crawler'); -const proverDependency = require('./app/modules/prover'); -const bmapiDependency = require('duniter-bma'); +const proverDependency = require('duniter-prover');//require('./app/modules/prover'); const routerDependency = require('./app/modules/router'); const MINIMAL_DEPENDENCIES = [ @@ -33,7 +30,6 @@ const MINIMAL_DEPENDENCIES = [ const DEFAULT_DEPENDENCIES = MINIMAL_DEPENDENCIES.concat([ { name: 'duniter-wizard', required: wizardDependency }, - { name: 'duniter-gen', required: genDependency }, { name: 'duniter-reset', required: resetDependency }, { name: 'duniter-chkconf', required: checkConfDependency }, { name: 'duniter-exportbc', required: exportBcDependency }, @@ -41,10 +37,7 @@ const DEFAULT_DEPENDENCIES = MINIMAL_DEPENDENCIES.concat([ { name: 'duniter-revert', required: revertDependency }, { name: 'duniter-daemon', required: daemonDependency }, { name: 'duniter-psignal', required: pSignalDependency }, - { name: 'duniter-crawler', required: crawlerDependency }, - { name: 'duniter-bmapi', required: bmapiDependency }, - { name: 'duniter-router', required: routerDependency }, - { name: 'duniter-keypair', required: dkeypairDependency } + { name: 'duniter-router', required: routerDependency } ]); const PRODUCTION_DEPENDENCIES = DEFAULT_DEPENDENCIES.concat([ @@ -263,9 +256,6 @@ function Stack(dependencies) { // Start services and streaming between them () => co(function*() { - const modules = streams.input.concat(streams.process).concat(streams.output).concat(streams.neutral); - // Any streaming module must implement a `startService` method - yield modules.map(module => module.startService()); // All inputs write to global INPUT stream for (const module of streams.input) module.pipe(INPUT); // All processes read from global INPUT stream @@ -274,6 +264,9 @@ function Stack(dependencies) { for (const module of streams.process) module.pipe(PROCESS); // All ouputs read from global PROCESS stream for (const module of streams.output) PROCESS.pipe(module); + // Any streaming module must implement a `startService` method + const modules = streams.input.concat(streams.process).concat(streams.output).concat(streams.neutral); + yield modules.map(module => module.startService()); }), // Stop services and streaming between them diff --git a/package.json b/package.json index 2d1374520d9cbcdb2aefc702be85dc9145f7cd26..19a25b9d458df177acb24708de86eccabd26b5ce 100644 --- a/package.json +++ b/package.json @@ -42,17 +42,17 @@ "colors": "1.1.2", "commander": "2.9.0", "daemonize2": "0.4.2", - "duniter-bma": "duniter/duniter-bma", - "duniter-crawler": "duniter/duniter-crawler", - "duniter-keypair": "duniter/duniter-keypair", + "duniter-bma": "0.1.0", + "duniter-crawler": "0.1.0", + "duniter-keypair": "0.1.1", + "duniter-prover": "0.1.0", + "duniter-common": "0.1.0", "event-stream": "3.3.4", "inquirer": "0.8.5", "jison": "0.4.17", "merkle": "0.5.1", "moment": "2.15.1", - "naclb": "1.3.7", "node-pre-gyp": "0.6.32", - "node-uuid": "1.4.7", "optimist": "0.6.1", "parallelshell": "2.0.0", "q": "1.4.1", @@ -63,7 +63,6 @@ "sha1": "1.1.1", "sqlite3": "3.1.4", "superagent": "2.3.0", - "tweetnacl": "0.14.3", "underscore": "1.8.3", "unzip": "0.1.11", "unzip2": "0.2.5", diff --git a/server.js b/server.js index 768bdb7ed9599a2c70a72a162a950a7225af2f9c..954f082e9352e740cfbf3030a303f0b39a77f9ca 100644 --- a/server.js +++ b/server.js @@ -12,10 +12,9 @@ const parsers = require('./app/lib/streams/parsers'); const constants = require('./app/lib/constants'); const fileDAL = require('./app/lib/dal/fileDAL'); const jsonpckg = require('./package.json'); -const keyring = require('./app/lib/crypto/keyring'); +const keyring = require('duniter-common').keyring; const directory = require('./app/lib/system/directory'); -const dos2unix = require('./app/lib/system/dos2unix'); -const rawer = require('./app/lib/ucp/rawer'); +const rawer = require('duniter-common').rawer; function Server (home, memoryOnly, overrideConf) { @@ -32,23 +31,26 @@ function Server (home, memoryOnly, overrideConf) { // External libs that.lib = {}; - that.lib.keyring = require('./app/lib/crypto/keyring'); + that.lib.keyring = require('duniter-common').keyring; that.lib.Identity = require('./app/lib/entity/identity'); + that.lib.Certification = require('./app/lib/entity/certification'); that.lib.Transaction = require('./app/lib/entity/transaction'); that.lib.Peer = require('./app/lib/entity/peer'); that.lib.Membership = require('./app/lib/entity/membership'); that.lib.Block = require('./app/lib/entity/block'); that.lib.Stat = require('./app/lib/entity/stat'); - that.lib.rawer = require('./app/lib/ucp/rawer'); + that.lib.rawer = require('duniter-common').rawer; + that.lib.parsers = require('./app/lib/streams/parsers'); that.lib.http2raw = require('duniter-bma').duniter.methods.http2raw; - that.lib.dos2unix = require('./app/lib/system/dos2unix'); + that.lib.dos2unix = require('duniter-common').dos2unix; that.lib.contacter = require('duniter-crawler').duniter.methods.contacter; that.lib.bma = require('duniter-bma').duniter.methods.bma; that.lib.network = require('./app/lib/system/network'); that.lib.constants = require('./app/lib/constants'); - that.lib.ucp = require('./app/lib/ucp/buid'); - that.lib.hashf = require('./app/lib/ucp/hashf'); + that.lib.ucp = require('duniter-common').buid; + that.lib.hashf = require('duniter-common').hashf; that.lib.indexer = require('./app/lib/dup/indexer'); + that.lib.rules = require('./app/lib/rules'); that.MerkleService = require("./app/lib/helpers/merkle"); that.IdentityService = require('./app/service/IdentityService')(); @@ -103,7 +105,6 @@ function Server (home, memoryOnly, overrideConf) { const defaultValues = { remoteipv6: that.conf.ipv6, remoteport: that.conf.port, - cpu: constants.DEFAULT_CPU, c: constants.CONTRACT.DEFAULT.C, dt: constants.CONTRACT.DEFAULT.DT, ud0: constants.CONTRACT.DEFAULT.UD0, @@ -320,14 +321,6 @@ function Server (home, memoryOnly, overrideConf) { this.disconnect = () => Promise.resolve(that.dal && that.dal.close()); - // Unit Tests or Preview method - this.doMakeNextBlock = (manualValues) => that.BlockchainService.makeNextBlock(null, null, manualValues); - - this.doCheckBlock = (block) => { - const parsed = parsers.parseBlock.syncWrite(block.getRawSigned()); - return that.BlockchainService.checkBlock(parsed, false); - }; - this.revert = () => this.BlockchainService.revertCurrentBlock(); this.revertTo = (number) => co(function *() { @@ -353,8 +346,6 @@ function Server (home, memoryOnly, overrideConf) { this.singleWritePromise = (obj) => that.submit(obj); - this.applyCPU = (cpu) => that.BlockchainService.changeProverCPUSetting(cpu); - this.rawer = rawer; this.writeRaw = (raw, type) => co(function *() { diff --git a/test/fast/crypto/crypto.js b/test/fast/crypto/crypto.js deleted file mode 100644 index fe09c14adb7e75c2c6dd185266ec89b69a6e154a..0000000000000000000000000000000000000000 --- a/test/fast/crypto/crypto.js +++ /dev/null @@ -1,50 +0,0 @@ -"use strict"; -const should = require('should'); -const co = require('co'); -const nacl = require('tweetnacl'); -const base58 = require('../../../app/lib/crypto/base58'); -const keyring = require('../../../app/lib/crypto/keyring'); - -const enc = nacl.util.encodeBase64, - dec = nacl.util.decodeBase64; - -let pub, sec, rawPub, rawSec; - -describe('ed25519 tests:', function(){ - - before(() => co(function*() { - // Generate the keypair - const keyPair = keyring.Key('HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP'); - pub = base58.decode(keyPair.publicKey); - sec = base58.decode(keyPair.secretKey); - rawPub = base58.encode(pub); - rawSec = base58.encode(sec); - })); - - //it('good signature from existing secret key should be verified', function(done){ - // const keys = nacl.sign.scryptKeyPair.fromSecretKey(dec("TM0Imyj/ltqdtsNG7BFOD1uKMZ81q6Yk2oz27U+4pvs9QBfD6EOJWpK3CqdNG368nJgszy7ElozAzVXxKvRmDA==")); - // const msg = "cg=="; - // const goodSig = dec("52Hh9omo9rxklulAE7gvVeYvAq0GgXYoZE2NB/gzehpCYIT04bMcGIs5bhYLaH93oib34jsVMWs9Udadr1B+AQ=="); - // const sig = crypto.signSync(msg, keys.secretKey); - // sig.should.equal(enc(goodSig)); - // crypto.verify(msg, sig, enc(keys.publicKey)).should.be.true; - // done(); - //}); - - it('good signature from generated key should be verified', function(done){ - const msg = "Some message to be signed"; - const sig = keyring.Key(rawPub, rawSec).signSync(msg); - const verified = keyring.verify(msg, sig, rawPub); - verified.should.equal(true); - done(); - }); - - it('wrong signature from generated key should NOT be verified', function(done){ - const msg = "Some message to be signed"; - const cor = dec(enc(msg) + 'delta'); - const sig = keyring.Key(rawPub, rawSec).signSync(msg); - const verified = keyring.verify(cor, sig, rawPub); - verified.should.equal(false); - done(); - }); -}); diff --git a/test/fast/pow/pow-engine.js b/test/fast/pow/pow-engine.js deleted file mode 100644 index 832468fd73c84e4750713409b23dcede6fdd46ae..0000000000000000000000000000000000000000 --- a/test/fast/pow/pow-engine.js +++ /dev/null @@ -1,119 +0,0 @@ -"use strict"; - -const co = require('co'); -const should = require('should'); -const engine = require('../../../app/lib/pow/engine'); - -describe('PoW Engine', () => { - - it('should start with status "ready", then "idle"', () => co(function*(){ - const e1 = engine(); - (yield e1.status()).should.equal('ready'); - (yield e1.status()).should.equal('ready'); - yield e1.setValue('autokillTimeout', 10); - })); - - it('should automatically close itself if no signal is sent', () => co(function*(){ - const e1 = engine(); - (yield e1.status()).should.equal('ready'); - (yield e1.status()).should.equal('ready'); - yield e1.setValue('autokillTimeout', 50); - (yield e1.status()).should.equal('ready'); - (yield e1.status()).should.equal('ready'); - yield new Promise((res) => setTimeout(res, 100)); - e1.isConnected().should.equal(false); - })); - - it('should NOT automatically close itself too early', () => co(function*(){ - const e1 = engine(); - e1.isConnected().should.equal(false); - (yield e1.status()).should.equal('ready'); - e1.isConnected().should.equal(true); - (yield e1.status()).should.equal('ready'); - yield e1.setValue('autokillTimeout', 200); - yield new Promise((res) => setTimeout(res, 100)); - e1.isConnected().should.equal(true); - yield new Promise((res) => setTimeout(res, 50)); - e1.isConnected().should.equal(true); - yield new Promise((res) => setTimeout(res, 50)); - e1.isConnected().should.equal(true); - yield new Promise((res) => setTimeout(res, 30)); - e1.isConnected().should.equal(false); - })); - - it('should be identifiable', () => co(function*(){ - const e1 = engine(); - e1.isConnected().should.equal(false); - (yield e1.status()).should.equal('ready'); - e1.isConnected().should.equal(true); - (yield e1.setValue('identify', { pubkey: 'pub1', identifier: 'id1' })).should.equal('OK'); - (yield e1.getValue('pubkey')).should.equal('pub1'); - (yield e1.getValue('id')).should.equal('id1'); - yield new Promise((res) => setTimeout(res, 10)); - })); - - it('should be configurable', () => co(function*(){ - const e1 = engine(); - e1.isConnected().should.equal(false); - (yield e1.status()).should.equal('ready'); - e1.isConnected().should.equal(true); - (yield e1.setValue('conf', { cpu: 0.2, prefix: '34' })).should.deepEqual({ currentCPU: 0.2, prefix: 34000000000000 }); - (yield e1.getValue('cpu')).should.equal(0.2); - (yield e1.getValue('prefix')).should.equal(34000000000000); - })); - - it('should be able to make a proof', () => co(function*(){ - const e1 = engine(); - (yield e1.status()).should.equal('ready'); - (yield e1.setValue('identify', { pubkey: 'pub1', identifier: 'id1' })).should.equal('OK'); - const block = { number: 35 }; - const nonceBeginning = 0; - const zeros = 2; - const highMark = 'A'; - const pair = { - pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', - sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP' - }; - const forcedTime = 1; - const medianTimeBlocks = 20; - const avgGenTime = 5 * 60; - const proof = yield e1.prove(block, nonceBeginning, zeros, highMark, pair, forcedTime, medianTimeBlocks, avgGenTime); - proof.should.deepEqual({ - pow: { - block: { - number: 35, - time: 1, - inner_hash: '785EEAC3FB737D67FA56B9C82F5F6E7D4DF87988FF1785AFD4A080272C0C9414', - nonce: 202, - hash: '00729594838C945EC291D00997FB8C4254B3949CFE8295A68C78A9FAABE90106', - signature: 'cTFtHlldwptnm6hjw+f0DzkUtYiCbhHAnxXsj1B7V6V8tDUcFNNlGAPqZvVXrZevwjkAGm0pgdUCrdFGB6+FCw==' - }, - testsCount: 201, - pow: '00729594838C945EC291D00997FB8C4254B3949CFE8295A68C78A9FAABE90106', - } - }); - })); - - it('should be able to stop a proof', () => co(function*(){ - const e1 = engine(); - (yield e1.status()).should.equal('ready'); - (yield e1.setValue('identify', { pubkey: 'pub1', identifier: 'id1' })).should.equal('OK'); - const block = { number: 26 }; - const nonceBeginning = 0; - const zeros = 10; // Requires hundreds of thousands of tries probably - const highMark = 'A'; - const pair = { - pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', - sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP' - }; - const forcedTime = 1; - const medianTimeBlocks = 20; - const proofPromise = e1.prove(block, nonceBeginning, zeros, highMark, pair, forcedTime, medianTimeBlocks); - yield new Promise((res) => setTimeout(res, 100)); - (yield e1.cancel()).should.equal('cancelling'); - (yield e1.cancel()).should.equal('cancelling'); - const proof = yield proofPromise; - (yield e1.cancel()).should.equal('ready'); - should.not.exist(proof); - })); -}); diff --git a/test/integration/cli.js b/test/integration/cli.js index 3935e242b18451556b2a7bb8dfe6a9319fa1cf5f..940cad33fc31f35aef74317f47349e2848b2a4d0 100644 --- a/test/integration/cli.js +++ b/test/integration/cli.js @@ -8,7 +8,7 @@ const _ = require('underscore'); const toolbox = require('./tools/toolbox'); const duniter = require('../../index'); const merkleh = require('../../app/lib/helpers/merkle'); -const hashf = require('../../app/lib/ucp/hashf'); +const hashf = require('duniter-common').hashf; const constants = require('../../app/lib/constants'); const Merkle = require('../../app/lib/entity/merkle'); diff --git a/test/integration/continuous-proof.js b/test/integration/continuous-proof.js index f2bb6c8a78a42fa7e2a1535d9d4c927e87640314..34dcd21a9700b57eac63b9f9c4e2004b9834a41d 100644 --- a/test/integration/continuous-proof.js +++ b/test/integration/continuous-proof.js @@ -5,8 +5,7 @@ const should = require('should'); const user = require('./tools/user'); const toolbox = require('./tools/toolbox'); const constants = require('../../app/lib/constants'); -const keyring = require('../../app/lib/crypto/keyring'); -const blockProver = require('../../app/lib/computation/blockProver'); +const keyring = require('duniter-common').keyring; // Trace these errors process.on('unhandledRejection', (reason) => { @@ -15,6 +14,7 @@ process.on('unhandledRejection', (reason) => { }); const s1 = toolbox.server({ + cpu: 1, powDelay: 1000, powMin: 32, pair: { @@ -42,18 +42,17 @@ describe("Continous proof-of-work", function() { })); it('should automatically stop waiting if nothing happens', () => co(function*() { - s1.permaProver.should.have.property('loops').equal(0); - const PREVIOUS_VALUE = constants.POW_SECURITY_RETRY_DELAY; - constants.POW_SECURITY_RETRY_DELAY = 10; + s1.conf.powSecurityRetryDelay = 10; let start = Date.now(); s1.startBlockComputation(); + s1.permaProver.should.have.property('loops').equal(0); yield s1.until('block', 1); s1.permaProver.should.have.property('loops').equal(1); (start - Date.now()).should.be.belowOrEqual(1000); yield s1.stopBlockComputation(); yield new Promise((resolve) => setTimeout(resolve, 100)); s1.permaProver.should.have.property('loops').equal(2); - constants.POW_SECURITY_RETRY_DELAY = PREVIOUS_VALUE; + s1.conf.powSecurityRetryDelay = 10 * 60 * 1000; yield s1.revert(); s1.permaProver.loops = 0; })); diff --git a/test/integration/forwarding.js b/test/integration/forwarding.js index 8ac1a472392eaac4a17ffda1b5dc29bd8873162d..cdbf5c7d84bbce4f2ced553461061881e55e1ee4 100644 --- a/test/integration/forwarding.js +++ b/test/integration/forwarding.js @@ -9,6 +9,7 @@ const user = require('./tools/user'); const jspckg = require('../../package'); const MEMORY_MODE = true; +require('duniter-bma').duniter.methods.noLimit(); // Disables the HTTP limiter describe("Forwarding", function() { diff --git a/test/integration/http_api.js b/test/integration/http_api.js index 7ff64280d49100304af072d0aac308e1b478aab4..820593a1b4885de85f17f41fbd0ca0bf397f6710 100644 --- a/test/integration/http_api.js +++ b/test/integration/http_api.js @@ -54,7 +54,7 @@ describe("HTTP API", function() { function makeBlockAndPost(theServer) { return function() { - return theServer.doMakeNextBlock() + return require('duniter-prover').duniter.methods.generateAndProveTheNext(theServer) .then(postBlock(theServer)); }; } diff --git a/test/integration/proof-of-work.js b/test/integration/proof-of-work.js index c28e751ac58848be27bd7cb7bda26be261952291..1f2a17f83d92f0cb4376bf4d1baf85d4117ef3e2 100644 --- a/test/integration/proof-of-work.js +++ b/test/integration/proof-of-work.js @@ -3,9 +3,10 @@ const co = require('co'); const should = require('should'); const toolbox = require('./tools/toolbox'); +const Block = require('../../app/lib/entity/block'); const constants = require('../../app/lib/constants'); -const keyring = require('../../app/lib/crypto/keyring'); -const blockProver = require('../../app/lib/computation/blockProver'); +const logger = require('../../app/lib/logger')(); +const blockProver = require('duniter-prover').duniter.methods.blockProver; /*** conf.medianTimeBlocks @@ -18,32 +19,26 @@ keyring from Key const intermediateProofs = []; const prover = blockProver({ - push: (data) => intermediateProofs.push(data) -}); - -prover.setConfDAL({ - cpu: 1.0 // 80% + push: (data) => intermediateProofs.push(data), + conf: { + cpu: 1.0, // 80%, + pair: { + pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', + sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP' + } }, - null, - keyring.Key( - 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', - '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP' -)); + logger, + lib: { constants, Block } +}); const now = 1474382274 * 1000; const MUST_START_WITH_A_ZERO = 16; const MUST_START_WITH_TWO_ZEROS = 32; -const BACKUP_HANDICAP = constants.POW_MAXIMUM_ACCEPTABLE_HANDICAP; - constants.CORES_MAXIMUM_USE_IN_PARALLEL = 1; // For simple tests. Can be changed to test multiple cores. describe("Proof-of-work", function() { - before(() => { - constants.POW_MAXIMUM_ACCEPTABLE_HANDICAP = 8; - }); - it('should be able to find an easy PoW', () => co(function*() { let block = yield prover.prove({ issuer: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', @@ -113,6 +108,8 @@ describe("Proof-of-work", function() { it('should be able to cancel a waiting on other PoW receival', () => co(function*() { const now = 1474464481; const res = yield toolbox.simpleNetworkOf2NodesAnd2Users({ + powSecurityRetryDelay: 10 * 60 * 1000, + powMaxHandicap: 8, percentRot: 1, powMin: 35 }), s1 = res.s1, s2 = res.s2; @@ -164,8 +161,4 @@ describe("Proof-of-work", function() { yield s1.expectJSON('/blockchain/current', { number: 5 }); yield s2.expectJSON('/blockchain/current', { number: 5 }); })); - - after(() => { - constants.POW_MAXIMUM_ACCEPTABLE_HANDICAP = BACKUP_HANDICAP; - }); }); diff --git a/test/integration/start_generate_blocks.js b/test/integration/start_generate_blocks.js index 61e1959acfff1ff93907429b637e9cf906cc9f16..8ee4b148f9b33d4e973b6430a2e7f7d75ba0c8ed 100644 --- a/test/integration/start_generate_blocks.js +++ b/test/integration/start_generate_blocks.js @@ -72,7 +72,7 @@ describe("Generation", function() { yield server.bma.openConnections(); require('../../app/modules/router').duniter.methods.routeToNetwork(server); yield server.PeeringService.generateSelfPeer(server.conf, 0); - const prover = require('../../app/modules/prover').duniter.methods.prover(server); + const prover = require('duniter-prover').duniter.methods.prover(server); server.startBlockComputation = () => prover.startService(); server.stopBlockComputation = () => prover.stopService(); } diff --git a/test/integration/tools/commit.js b/test/integration/tools/commit.js index fd06c8b2cc6ae0036d52a573aa29cd964efc56c6..1385e44b40fc2a396bdf275226f2cecfcce2b0b8 100644 --- a/test/integration/tools/commit.js +++ b/test/integration/tools/commit.js @@ -12,7 +12,7 @@ module.exports = function makeBlockAndPost(theServer, extraProps) { manualValues = _.extend(manualValues, extraProps); } return co(function *() { - let proven = yield theServer.doMakeNextBlock(manualValues); + let proven = yield require('duniter-prover').duniter.methods.generateAndProveTheNext(theServer, null, null, manualValues); return postBlock(theServer)(proven); }); }; diff --git a/test/integration/tools/node.js b/test/integration/tools/node.js index c66b56f53cf247da1bb1027cb8fb323e939ccb4a..3d90d172d652d4ebc795cba2b3a9f1ee092e5366 100644 --- a/test/integration/tools/node.js +++ b/test/integration/tools/node.js @@ -80,9 +80,9 @@ function Node (dbName, options) { block: function(callback){ co(function *() { try { - const block2 = yield that.server.BlockchainService.generateNext(params); + const block2 = yield require('duniter-prover').duniter.methods.generateTheNextBlock(that.server, params); const trial2 = yield that.server.getBcContext().getIssuerPersonalizedDifficulty(that.server.keyPair.publicKey); - const block = yield that.server.BlockchainService.makeNextBlock(block2, trial2, params); + const block = yield require('duniter-prover').duniter.methods.generateAndProveTheNext(that.server, block2, trial2, params); callback(null, block); } catch (e) { callback(e); @@ -142,6 +142,9 @@ function Node (dbName, options) { function service(callback) { return function () { const stack = duniter.statics.simpleStack(); + for (const name of ['duniter-keypair', 'duniter-bma']) { + stack.registerDependency(require(name), name); + } stack.registerDependency({ duniter: { config: { diff --git a/test/integration/tools/toolbox.js b/test/integration/tools/toolbox.js index d899f12b38b9f82390ca9bf121e0f4f89ace139e..fb5f56a83d64af6c10de5d84a77207e6a12381bd 100644 --- a/test/integration/tools/toolbox.js +++ b/test/integration/tools/toolbox.js @@ -242,7 +242,7 @@ module.exports = { }); server.makeNext = (overrideProps) => co(function*() { - const block = yield server.doMakeNextBlock(overrideProps || {}); + const block = yield require('duniter-prover').duniter.methods.generateAndProveTheNext(server, null, null, overrideProps || {}); return Block.statics.fromJSON(block); }); @@ -289,10 +289,16 @@ module.exports = { require('../../../app/modules/router').duniter.methods.routeToNetwork(server); }); - const prover = require('../../../app/modules/prover').duniter.methods.prover(server); - server.permaProver = prover.permaProver; - server.pipe(prover); - server.startBlockComputation = () => prover.startService(); + let prover; + server.startBlockComputation = () => { + if (!prover) { + prover = require('duniter-prover').duniter.methods.prover(server); + server.permaProver = prover.permaProver; + server.pipe(prover); + } + prover.startService(); + }; + // server.startBlockComputation = () => prover.startService(); server.stopBlockComputation = () => prover.stopService(); return server; diff --git a/test/integration/tools/user.js b/test/integration/tools/user.js index 14d774e016e66dcdadb425199a1da75d08e94b54..2f8d4db5d9a4569895194b84133e421fc6f3b23d 100644 --- a/test/integration/tools/user.js +++ b/test/integration/tools/user.js @@ -5,10 +5,10 @@ const _ = require('underscore'); const async = require('async'); const request = require('request'); const contacter = require('duniter-crawler').duniter.methods.contacter; -const ucp = require('../../../app/lib/ucp/buid'); +const ucp = require('duniter-common').buid; const parsers = require('../../../app/lib/streams/parsers'); -const keyring = require('../../../app/lib/crypto/keyring'); -const rawer = require('../../../app/lib/ucp/rawer'); +const keyring = require('duniter-common').keyring; +const rawer = require('duniter-common').rawer; const constants = require('../../../app/lib/constants'); const Identity = require('../../../app/lib/entity/identity'); const Certification = require('../../../app/lib/entity/certification'); diff --git a/test/integration/v1.0-modules-api.js b/test/integration/v1.0-modules-api.js index c2591618e17fdfa18dd54c256633fbda008c5205..acf5542edee43ba74930e1038b1c5505a2b8bc8b 100644 --- a/test/integration/v1.0-modules-api.js +++ b/test/integration/v1.0-modules-api.js @@ -96,6 +96,7 @@ describe("v1.0 Module API", () => { } }; + stack.registerDependency(require('duniter-keypair'), 'duniter-keypair'); stack.registerDependency(configurationDependency, 'duniter-configuration'); stack.registerDependency(returnConfDependency, 'duniter-gimme-conf'); })); @@ -165,10 +166,11 @@ describe("v1.0 Module API", () => { that.push(tx); } }); - fakeO = new FakeStream((that, data) => { + fakeO = new FakeStream((that, data, enc, done) => { if (data.issuers) { that.resolveData(); } + done && done(); }); // Fake output has a special promise of data receival, for our tests fakeO.outputed = querablep(new Promise((res) => fakeO.resolveData = res)); @@ -224,6 +226,8 @@ describe("v1.0 Module API", () => { } }; + stack.registerDependency(require('duniter-keypair'), 'duniter-keypair'); + stack.registerDependency(require('duniter-bma'), 'duniter-bma'); stack.registerDependency(dummyStartServiceDependency, 'duniter-dummy-start'); stack.registerDependency(dummyStopServiceDependency, 'duniter-dummy-stop'); }));