Commit f71880a9 authored by Cédric Moreau's avatar Cédric Moreau
Browse files

[fix] #1037 Migrate module "duniter-prover"

parent 9598ed09
......@@ -23,5 +23,7 @@ app/modules/daemon.js
app/modules/export-bc.js
app/modules/check-config.js
app/modules/config.js
app/modules/prover/*.js
app/modules/prover/lib/*.js
test/*.js
test/**/*.js
\ No newline at end of file
......@@ -51,6 +51,8 @@ app/lib/rules/*.js*
app/lib/logger*js*
app/service/*.js*
app/lib/wot.js*
app/modules/prover/*.js*
app/modules/prover/lib/*.js*
app/modules/router*.js*
app/modules/wizard.js*
app/modules/revert.js*
......
......@@ -60,7 +60,7 @@ export class BlockchainContext {
* Gets a copy of vHEAD, extended with some extra properties.
* @param props The extra properties to add.
*/
async getvHeadCopy(props: any): Promise<any> {
async getvHeadCopy(props: any = {}): Promise<any> {
if (!this.vHEAD) {
await this.refreshHead();
}
......
......@@ -10,7 +10,13 @@ export class ConfDTO {
public currency: string,
public endpoints: string[],
public rmEndpoints: string[],
public rootoffset: number,
public upInterval: number,
public cpu: number,
public nbCores: number,
public prefix: number,
public powSecurityRetryDelay: number,
public powMaxHandicap: number,
public c: number,
public dt: number,
public dtReeval: number,
......@@ -46,6 +52,6 @@ export class ConfDTO {
) {}
static mock() {
return new ConfDTO("", "", [], [], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, false, 0, 0, 0, 0, 0, null, 0, "", "", "")
return new ConfDTO("", "", [], [], 0, 0, 0.6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, false, 0, 0, 0, 0, 0, null, 0, "", "", "")
}
}
\ No newline at end of file
"use strict";
import {BlockDTO} from "../dto/BlockDTO"
import {ConfDTO} from "../dto/ConfDTO"
import {FileDAL} from "../dal/fileDAL"
import {DBBlock} from "../db/DBBlock"
import {DBIdentity} from "../dal/sqliteDAL/IdentityDAL"
import {TransactionDTO} from "../dto/TransactionDTO"
import * as local_rules from "./local_rules"
const co = require('co');
const _ = require('underscore');
const common = require('duniter-common');
const indexer = require('../indexer').Indexer
......@@ -158,9 +155,13 @@ export const GLOBAL_RULES_HELPERS = {
// Functions used in an external context too
checkMembershipBlock: (ms:any, current:DBBlock, conf:ConfDTO, dal:FileDAL) => checkMSTarget(ms, current ? { number: current.number + 1} : { number: 0 }, conf, dal),
checkCertificationIsValid: (cert:any, current:DBBlock, findIdtyFunc:any, conf:ConfDTO, dal:FileDAL) => checkCertificationIsValid(current ? current : { number: 0 }, cert, findIdtyFunc, conf, dal),
checkCertificationIsValid: (cert:any, current:DBBlock, findIdtyFunc:any, conf:ConfDTO, dal:FileDAL) => {
return checkCertificationIsValid(current ? current : { number: 0, currency: '' }, cert, findIdtyFunc, conf, dal)
},
checkCertificationIsValidForBlock: (cert:any, block:BlockDTO, idty:DBIdentity, conf:ConfDTO, dal:FileDAL) => checkCertificationIsValid(block, cert, () => idty, conf, dal),
checkCertificationIsValidForBlock: (cert:any, block:{ number:number, currency:string }, findIdtyFunc:(b:{ number:number, currency:string }, pubkey:string, dal:FileDAL) => Promise<any>, conf:ConfDTO, dal:FileDAL) => {
return checkCertificationIsValid(block, cert, findIdtyFunc, conf, dal)
},
isOver3Hops: async (member:any, newLinks:any, newcomers:string[], current:DBBlock, conf:ConfDTO, dal:FileDAL) => {
if (!current) {
......@@ -177,7 +178,7 @@ export const GLOBAL_RULES_HELPERS = {
checkExistsPubkey: (pub:string, dal:FileDAL) => dal.getWrittenIdtyByPubkey(pub),
checkSingleTransaction: (tx:TransactionDTO, block:{ medianTime: number }, conf:ConfDTO, dal:FileDAL, alsoCheckPendingTransactions:boolean) => GLOBAL_RULES_FUNCTIONS.checkSourcesAvailability({
checkSingleTransaction: (tx:TransactionDTO, block:{ medianTime: number }, conf:ConfDTO, dal:FileDAL, alsoCheckPendingTransactions:boolean = false) => GLOBAL_RULES_FUNCTIONS.checkSourcesAvailability({
transactions: [tx],
medianTime: block.medianTime
}, conf, dal, alsoCheckPendingTransactions),
......@@ -228,7 +229,7 @@ async function checkMSTarget (ms:any, block:any, conf:ConfDTO, dal:FileDAL) {
}
}
async function checkCertificationIsValid (block:any, cert:any, findIdtyFunc:any, conf:ConfDTO, dal:FileDAL) {
async function checkCertificationIsValid (block:{ number:number, currency:string }, cert:any, findIdtyFunc:(b:{ number:number, currency:string }, pubkey:string, dal:FileDAL) => Promise<any>, conf:ConfDTO, dal:FileDAL) {
if (block.number == 0 && cert.block_number != 0) {
throw Error('Number must be 0 for root block\'s certifications');
} else {
......@@ -250,10 +251,7 @@ async function checkCertificationIsValid (block:any, cert:any, findIdtyFunc:any,
throw Error('Certifier must be a member')
}
}
// TODO: weird call, we cannot just do "await findIdtyFunc(...)". There is a bug somewhere.
let idty = await co(function*() {
return yield findIdtyFunc(block, cert.to, dal)
})
let idty = await findIdtyFunc(block, cert.to, dal)
let current = block.number == 0 ? null : await dal.getCurrentBlockOrNull();
if (!idty) {
throw Error('Identity does not exist for certified');
......
const constants = require('../lib/constants');
const wizard = require('../lib/wizard');
const logger = require('../lib/logger').NewLogger('wizard');
module.exports = {
duniter: {
......@@ -11,6 +10,7 @@ module.exports = {
onConfiguredExecute: async (server:any) => {
await server.checkConfig()
const logger = require('../lib/logger').NewLogger('wizard')
logger.warn('Configuration seems correct.');
}
}]
......
"use strict";
const co = require('co');
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const blockGenerator_1 = require("./lib/blockGenerator");
const constants_1 = require("./lib/constants");
const blockProver_1 = require("./lib/blockProver");
const prover_1 = require("./lib/prover");
const async = require('async');
const contacter = require('duniter-crawler').duniter.methods.contacter;
const common = require('duniter-common');
const constants = require('./lib/constants');
const Prover = require('./lib/prover');
const blockGenerator = require('./lib/blockGenerator');
const blockProver = require('./lib/blockProver');
const Peer = common.document.Peer
module.exports = {
duniter: {
/*********** Permanent prover **************/
config: {
onLoading: (conf) => co(function*() {
if (conf.cpu === null || conf.cpu === undefined) {
conf.cpu = constants.DEFAULT_CPU;
}
conf.powSecurityRetryDelay = constants.POW_SECURITY_RETRY_DELAY;
conf.powMaxHandicap = constants.POW_MAXIMUM_ACCEPTABLE_HANDICAP;
}),
beforeSave: (conf) => co(function*() {
delete conf.powSecurityRetryDelay;
delete conf.powMaxHandicap;
})
},
service: {
output: (server, conf, logger) => {
const generator = blockGenerator(server);
server.generatorGetJoinData = generator.getSinglePreJoinData.bind(generator)
server.generatorComputeNewCerts = generator.computeNewCerts.bind(generator)
server.generatorNewCertsToLinks = generator.newCertsToLinks.bind(generator)
return new Prover(server, conf, logger)
}
},
methods: {
hookServer: (server) => {
const generator = blockGenerator(server);
server.generatorGetJoinData = generator.getSinglePreJoinData.bind(generator)
server.generatorComputeNewCerts = generator.computeNewCerts.bind(generator)
server.generatorNewCertsToLinks = generator.newCertsToLinks.bind(generator)
},
blockProver: blockProver,
prover: (server, conf, logger) => new Prover(server, conf, logger),
blockGenerator: (server, prover) => blockGenerator(server, prover),
generateTheNextBlock: (server, manualValues) => co(function*() {
const prover = blockProver(server);
const generator = blockGenerator(server, prover);
return generator.nextBlock(manualValues);
}),
generateAndProveTheNext: (server, block, trial, manualValues) => co(function*() {
const prover = blockProver(server);
const generator = blockGenerator(server, prover);
let res = yield generator.makeNextBlock(block, trial, manualValues);
return res
})
},
/*********** CLI gen-next + gen-root **************/
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.'},
{value: '--at <medianTime>', desc: 'With gen-next --show --check: allows to try in a future time.', parser: parseInt }
],
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];
const generator = blockGenerator(server, null);
return generateAndSend(program, host, port, difficulty, server, () => generator.nextBlock);
})
}, {
name: 'gen-root [host] [port] [difficulty]',
desc: 'Tries to generate the next block of the blockchain.',
preventIfRunning: true,
onDatabaseExecute: (server, conf, program, params) => co(function*() {
const host = params[0];
const port = params[1];
const difficulty = params[2];
const generator = blockGenerator(server, null);
let toDelete, catched = true;
do {
try {
yield generateAndSend(program, host, port, difficulty, server, () => generator.nextBlock);
catched = false;
} catch (e) {
toDelete = yield server.dal.idtyDAL.query('SELECT * FROM idty i WHERE 5 > (SELECT count(*) from cert c where c.`to` = i.pubkey)');
console.log('Deleting', toDelete.map(i => i.pubkey));
yield server.dal.idtyDAL.exec('DELETE FROM idty WHERE pubkey IN (' + toDelete.map(i => "'" + i.pubkey + "'").join(',') + ')');
yield server.dal.idtyDAL.exec('DELETE FROM cert WHERE `to` IN (' + toDelete.map(i => "'" + i.pubkey + "'").join(',') + ')');
yield server.dal.idtyDAL.exec('DELETE FROM cert WHERE `from` IN (' + toDelete.map(i => "'" + i.pubkey + "'").join(',') + ')');
}
} while (catched && toDelete.length);
console.log('Done');
})
}, {
name: 'gen-root-choose [host] [port] [difficulty]',
desc: 'Tries to generate root block, with choice of root members.',
preventIfRunning: true,
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.';
}
const generator = blockGenerator(server, null);
return generateAndSend(program, host, port, difficulty, server, () => generator.manualRoot);
})
}]
}
}
const Peer = common.document.Peer;
exports.ProverDependency = {
duniter: {
/*********** Permanent prover **************/
config: {
onLoading: (conf) => __awaiter(this, void 0, void 0, function* () {
if (conf.cpu === null || conf.cpu === undefined) {
conf.cpu = constants_1.Constants.DEFAULT_CPU;
}
conf.powSecurityRetryDelay = constants_1.Constants.POW_SECURITY_RETRY_DELAY;
conf.powMaxHandicap = constants_1.Constants.POW_MAXIMUM_ACCEPTABLE_HANDICAP;
}),
beforeSave: (conf) => __awaiter(this, void 0, void 0, function* () {
delete conf.powSecurityRetryDelay;
delete conf.powMaxHandicap;
})
},
service: {
output: (server) => {
const generator = new blockGenerator_1.BlockGenerator(server);
server.generatorGetJoinData = generator.getSinglePreJoinData.bind(generator);
server.generatorComputeNewCerts = generator.computeNewCerts.bind(generator);
server.generatorNewCertsToLinks = generator.newCertsToLinks.bind(generator);
return new prover_1.Prover(server);
}
},
methods: {
hookServer: (server) => {
const generator = new blockGenerator_1.BlockGenerator(server);
server.generatorGetJoinData = generator.getSinglePreJoinData.bind(generator);
server.generatorComputeNewCerts = generator.computeNewCerts.bind(generator);
server.generatorNewCertsToLinks = generator.newCertsToLinks.bind(generator);
},
prover: (server, conf, logger) => new prover_1.Prover(server),
blockGenerator: (server, prover) => new blockGenerator_1.BlockGeneratorWhichProves(server, prover),
generateTheNextBlock: (server, manualValues) => __awaiter(this, void 0, void 0, function* () {
const prover = new blockProver_1.BlockProver(server);
const generator = new blockGenerator_1.BlockGeneratorWhichProves(server, prover);
return generator.nextBlock(manualValues);
}),
generateAndProveTheNext: (server, block, trial, manualValues) => __awaiter(this, void 0, void 0, function* () {
const prover = new blockProver_1.BlockProver(server);
const generator = new blockGenerator_1.BlockGeneratorWhichProves(server, prover);
let res = yield generator.makeNextBlock(block, trial, manualValues);
return res;
})
},
/*********** CLI gen-next + gen-root **************/
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.' },
{ value: '--at <medianTime>', desc: 'With gen-next --show --check: allows to try in a future time.', parser: parseInt }
],
cli: [{
name: 'gen-next [host] [port] [difficulty]',
desc: 'Tries to generate the next block of the blockchain.',
onDatabaseExecute: (server, conf, program, params) => __awaiter(this, void 0, void 0, function* () {
const host = params[0];
const port = params[1];
const difficulty = params[2];
const generator = new blockGenerator_1.BlockGeneratorWhichProves(server, null);
return generateAndSend(program, host, port, difficulty, server, () => generator.nextBlock);
})
}, {
name: 'gen-root [host] [port] [difficulty]',
desc: 'Tries to generate the next block of the blockchain.',
preventIfRunning: true,
onDatabaseExecute: (server, conf, program, params) => __awaiter(this, void 0, void 0, function* () {
const host = params[0];
const port = params[1];
const difficulty = params[2];
const generator = new blockGenerator_1.BlockGeneratorWhichProves(server, null);
let toDelete, catched = true;
do {
try {
yield generateAndSend(program, host, port, difficulty, server, () => generator.nextBlock);
catched = false;
}
catch (e) {
toDelete = yield server.dal.idtyDAL.query('SELECT * FROM idty i WHERE 5 > (SELECT count(*) from cert c where c.`to` = i.pubkey)');
console.log('Deleting', toDelete.map((i) => i.pubkey));
yield server.dal.idtyDAL.exec('DELETE FROM idty WHERE pubkey IN (' + toDelete.map((i) => "'" + i.pubkey + "'").join(',') + ')');
yield server.dal.idtyDAL.exec('DELETE FROM cert WHERE `to` IN (' + toDelete.map((i) => "'" + i.pubkey + "'").join(',') + ')');
yield server.dal.idtyDAL.exec('DELETE FROM cert WHERE `from` IN (' + toDelete.map((i) => "'" + i.pubkey + "'").join(',') + ')');
}
} while (catched && toDelete.length);
console.log('Done');
})
}, {
name: 'gen-root-choose [host] [port] [difficulty]',
desc: 'Tries to generate root block, with choice of root members.',
preventIfRunning: true,
onDatabaseExecute: (server, conf, program, params) => __awaiter(this, void 0, void 0, 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.';
}
const generator = new blockGenerator_1.BlockGenerator(server);
return generateAndSend(program, host, port, difficulty, server, () => generator.manualRoot);
})
}]
}
};
function generateAndSend(program, host, port, difficulty, server, getGenerationMethod) {
const logger = server.logger;
return new Promise((resolve, reject) => {
async.waterfall([
function (next) {
const method = getGenerationMethod(server);
co(function*(){
const simulationValues = {}
if (program.show && program.check) {
if (program.at && !isNaN(program.at)) {
simulationValues.medianTime = program.at
const logger = server.logger;
return new Promise((resolve, reject) => {
async.waterfall([
function (next) {
const method = getGenerationMethod(server);
(() => __awaiter(this, void 0, void 0, function* () {
const simulationValues = {};
if (program.show && program.check) {
if (program.at && !isNaN(program.at)) {
simulationValues.medianTime = program.at;
}
}
const block = yield method(null, simulationValues);
next(null, block);
}))();
},
function (block, next) {
if (program.check) {
block.time = block.medianTime;
program.show && console.log(block.getRawSigned());
(() => __awaiter(this, void 0, void 0, function* () {
try {
const parsed = common.parsers.parseBlock.syncWrite(block.getRawSigned());
yield server.BlockchainService.checkBlock(parsed, false);
logger.info('Acceptable block');
next();
}
catch (e) {
next(e);
}
}))();
}
else {
logger.debug('Block to be sent: %s', block.getRawInnerPart());
async.waterfall([
function (subNext) {
proveAndSend(program, server, block, server.conf.pair.pub, parseInt(difficulty), host, parseInt(port), subNext);
}
], next);
}
}
}
const block = yield method(null, simulationValues);
next(null, block);
], (err, data) => {
err && reject(err);
!err && resolve(data);
});
},
function (block, next) {
if (program.check) {
block.time = block.medianTime;
program.show && console.log(block.getRawSigned());
co(function*(){
try {
const parsed = common.parsers.parseBlock.syncWrite(block.getRawSigned());
yield server.BlockchainService.checkBlock(parsed, false);
logger.info('Acceptable block');
next();
} catch (e) {
next(e);
}
});
}
else {
logger.debug('Block to be sent: %s', block.getRawInnerPart());
async.waterfall([
function (subNext) {
proveAndSend(program, server, block, server.conf.pair.pub, parseInt(difficulty), host, parseInt(port), subNext);
}
], next);
}
}
], (err, data) => {
err && reject(err);
!err && resolve(data);
});
});
}
function proveAndSend(program, server, block, issuer, difficulty, host, port, done) {
const logger = server.logger;
async.waterfall([
function (next) {
block.issuer = issuer;
program.show && console.log(block.getRawSigned());
co(function*(){
try {
const prover = blockProver(server);
const proven = yield prover.prove(block, difficulty);
const peer = Peer.fromJSON({
endpoints: [['BASIC_MERKLED_API', host, port].join(' ')]
});
program.show && console.log(proven.getRawSigned());
logger.info('Posted block ' + proven.getRawSigned());
const p = Peer.fromJSON(peer);
const contact = contacter(p.getHostPreferDNS(), p.getPort());
yield contact.postBlock(proven.getRawSigned());
} catch(e) {
next(e);
const logger = server.logger;
async.waterfall([
function (next) {
block.issuer = issuer;
program.show && console.log(block.getRawSigned());
(() => __awaiter(this, void 0, void 0, function* () {
try {
const prover = new blockProver_1.BlockProver(server);
const proven = yield prover.prove(block, difficulty);
const peer = Peer.fromJSON({
endpoints: [['BASIC_MERKLED_API', host, port].join(' ')]
});
program.show && console.log(proven.getRawSigned());
logger.info('Posted block ' + proven.getRawSigned());
const p = Peer.fromJSON(peer);
const contact = contacter(p.getHostPreferDNS(), p.getPort());
yield contact.postBlock(proven.getRawSigned());
}
catch (e) {
next(e);
}
}))();
}
});
}
], done);
], done);
}
//# sourceMappingURL=index.js.map
\ No newline at end of file
import {ConfDTO} from "../../lib/dto/ConfDTO"
import {BlockGenerator, BlockGeneratorWhichProves} from "./lib/blockGenerator"
import {Constants} from "./lib/constants"
import {BlockProver} from "./lib/blockProver"
import {Prover} from "./lib/prover"
const async = require('async');
const contacter = require('duniter-crawler').duniter.methods.contacter;
const common = require('duniter-common');
const Peer = common.document.Peer
export const ProverDependency = {
duniter: {
/*********** Permanent prover **************/
config: {
onLoading: async (conf:ConfDTO) => {
if (conf.cpu === null || conf.cpu === undefined) {
conf.cpu = Constants.DEFAULT_CPU;
}
conf.powSecurityRetryDelay = Constants.POW_SECURITY_RETRY_DELAY;
conf.powMaxHandicap = Constants.POW_MAXIMUM_ACCEPTABLE_HANDICAP;
},
beforeSave: async (conf:ConfDTO) => {
delete conf.powSecurityRetryDelay;
delete conf.powMaxHandicap;
}
},
service: {
output: (server:any) => {
const generator = new BlockGenerator(server);
server.generatorGetJoinData = generator.getSinglePreJoinData.bind(generator)
server.generatorComputeNewCerts = generator.computeNewCerts.bind(generator)
server.generatorNewCertsToLinks = generator.newCertsToLinks.bind(generator)
return new Prover(server)
}
},
methods: {
hookServer: (server:any) => {
const generator = new BlockGenerator(server);
server.generatorGetJoinData = generator.getSinglePreJoinData.bind(generator)
server.generatorComputeNewCerts = generator.computeNewCerts.bind(generator)