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

Protocol 0.2: added idtyWindow parameter

parent f1024d6e
......@@ -134,7 +134,8 @@ function WebAdmin (dbConf, overConf) {
sigWindow: conf.sigWindow,
stepMax: conf.stepMax,
ud0: conf.ud0,
xpercent: conf.xpercent
xpercent: conf.xpercent,
idtyWindow: conf.idtyWindow
});
pluggedConfP = co(function *() {
yield bmapi.closeConnections();
......
......@@ -452,6 +452,13 @@ function BlockGenerator(mainContext, prover) {
if (!identity) {
throw 'Identity with hash \'' + idHash + '\' not found';
}
if (identity.buid != constants.BLOCK.SPECIAL_BLOCK) {
let idtyBasedBlock = yield dal.getBlock(identity.buid);
let age = current.medianTime - idtyBasedBlock.medianTime;
if (age > conf.idtyWindow) {
throw 'Too old identity';
}
}
if (!identity.leaving) {
if (!current) {
// Look for certifications from initial joiners
......@@ -533,7 +540,7 @@ function BlockGenerator(mainContext, prover) {
block.parameters = block.number > 0 ? '' : [
conf.c, conf.dt, conf.ud0,
conf.sigPeriod, conf.sigStock, conf.sigWindow, conf.sigValidity,
conf.sigQty, conf.xpercent, conf.msValidity,
conf.sigQty, conf.idtyWindow, conf.xpercent, conf.msValidity,
conf.stepMax, conf.medianTimeBlocks, conf.avgGenTime, conf.dtDiffEval,
conf.blocksRot, (conf.percentRot == 1 ? "1.0" : conf.percentRot)
].join(':');
......
......@@ -474,14 +474,15 @@ function BlockchainContext() {
conf.sigWindow = parseInt(sp[5]);
conf.sigValidity = parseInt(sp[6]);
conf.sigQty = parseInt(sp[7]);
conf.xpercent = parseFloat(sp[8]);
conf.msValidity = parseInt(sp[9]);
conf.stepMax = parseInt(sp[10]);
conf.medianTimeBlocks = parseInt(sp[11]);
conf.avgGenTime = parseInt(sp[12]);
conf.dtDiffEval = parseInt(sp[13]);
conf.blocksRot = parseInt(sp[14]);
conf.percentRot = parseFloat(sp[15]);
conf.idtyWindow = parseInt(sp[8]);
conf.xpercent = parseFloat(sp[9]);
conf.msValidity = parseInt(sp[10]);
conf.stepMax = parseInt(sp[11]);
conf.medianTimeBlocks = parseInt(sp[12]);
conf.avgGenTime = parseInt(sp[13]);
conf.dtDiffEval = parseInt(sp[14]);
conf.blocksRot = parseInt(sp[15]);
conf.percentRot = parseFloat(sp[16]);
conf.currency = block.currency;
return dal.saveConf(conf).then(done).catch(done);
}
......
......@@ -167,13 +167,14 @@ module.exports = {
PREV_ISSUER: find("PreviousIssuer: (" + PUBKEY + ")"),
MEMBERS_COUNT:find("MembersCount: (" + ZERO_OR_POSITIVE_INT + ")"),
BLOCK_ISSUER:find('Issuer: (' + PUBKEY + ')'),
PARAMETERS: find("Parameters: (" + FLOAT + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + FLOAT + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + FLOAT + ")"),
PARAMETERS: find("Parameters: (" + FLOAT + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + FLOAT + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + FLOAT + ")"),
JOINER: exact(PUBKEY + ":" + SIGNATURE + ":" + BLOCK_UID + ":" + BLOCK_UID + ":" + USER_ID),
ACTIVE: exact(PUBKEY + ":" + SIGNATURE + ":" + BLOCK_UID + ":" + BLOCK_UID + ":" + USER_ID),
LEAVER: exact(PUBKEY + ":" + SIGNATURE + ":" + BLOCK_UID + ":" + BLOCK_UID + ":" + USER_ID),
REVOCATION: exact(PUBKEY + ":" + SIGNATURE),
EXCLUDED: exact(PUBKEY),
INNER_HASH: find("InnerHash: (" + FINGERPRINT + ")")
INNER_HASH: find("InnerHash: (" + FINGERPRINT + ")"),
SPECIAL_BLOCK: '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855'
},
TRANSACTION: {
HEADER: exact("TX:" + POSITIVE_INT + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + INTEGER + ":" + BOOLEAN + ":" + INTEGER),
......@@ -261,7 +262,7 @@ module.exports = {
SIGDELAY: 3600 * 24 * 365 * 5,
SIGPERIOD: 0, // Instant
SIGSTOCK: 40,
SIGWINDOW: 3600, // 2h
SIGWINDOW: 3600 * 24 * 7, // a week
SIGVALIDITY: 3600 * 24 * 365,
MSVALIDITY: 3600 * 24 * 365,
SIGQTY: 5,
......@@ -271,7 +272,8 @@ module.exports = {
POWDELAY: 0,
AVGGENTIME: 16 * 60,
DTDIFFEVAL: 10,
MEDIANTIMEBLOCKS: 20
MEDIANTIMEBLOCKS: 20,
IDTYWINDOW: 3600 * 24 * 7 // a week
},
DSEN_P: 1.2 // dSen proportional factor
......
......@@ -33,6 +33,7 @@ function ConfDAL(rootPath, qioFS, parentCore, localDAL, AbstractStorage) {
"sigWindow": parseInt(conf.sigWindow,10),
"sigValidity": parseInt(conf.sigValidity,10),
"sigQty": parseInt(conf.sigQty,10),
"idtyWindow": parseInt(conf.idtyWindow,10),
"xpercent": parseFloat(conf.xpercent,10),
"msValidity": parseInt(conf.msValidity,10),
"stepMax": parseInt(3,10), // uCoin only handles 3 step currencies for now
......
......@@ -211,6 +211,27 @@ rules.FUNCTIONS = {
return true;
}),
checkIdentitiesAreWritable: (block, conf, dal) => co(function *() {
let current = yield dal.getCurrent();
for (let i = 0, len = block.identities.length; i < len; i++) {
let idty = Identity.statics.fromInline(block.identities[i]);
let found = yield dal.getWrittenIdtyByUID(idty.uid);
if (found) {
throw Error('Identity already used');
}
if (current && idty.buid != constants.BLOCK.SPECIAL_BLOCK) {
// Because the window rule does not apply on initial certifications
let basedBlock = yield dal.getBlock(idty.buid);
// Check if writable
let duration = current.medianTime - parseInt(basedBlock.medianTime);
if (duration > conf.idtyWindow) {
throw Error('Identity is too old and cannot be written');
}
}
}
return true;
}),
checkCertificationsAreWritable: (block, conf, dal) => co(function *() {
let current = yield dal.getCurrent();
for (let i = 0, len = block.certifications.length; i < len; i++) {
......
......@@ -78,6 +78,7 @@ rules.ALIAS = {
yield rules.GLOBAL.checkTimes(block, conf, dal);
yield rules.GLOBAL.checkIdentityUnicity(block, conf, dal);
yield rules.GLOBAL.checkPubkeyUnicity(block, conf, dal);
yield rules.GLOBAL.checkIdentitiesAreWritable(block, conf, dal);
yield rules.GLOBAL.checkJoiners(block, conf, dal);
yield rules.GLOBAL.checkJoinersHaveEnoughCertifications(block, conf, dal);
yield rules.GLOBAL.checkJoinersAreNotOudistanced(block, conf, dal);
......@@ -110,6 +111,7 @@ rules.ALIAS = {
yield rules.GLOBAL.checkTimes(block, conf, dal);
yield rules.GLOBAL.checkIdentityUnicity(block, conf, dal);
yield rules.GLOBAL.checkPubkeyUnicity(block, conf, dal);
yield rules.GLOBAL.checkIdentitiesAreWritable(block, conf, dal);
yield rules.GLOBAL.checkJoiners(block, conf, dal);
yield rules.GLOBAL.checkJoinersHaveEnoughCertifications(block, conf, dal);
yield rules.GLOBAL.checkJoinersAreNotOudistanced(block, conf, dal);
......
......@@ -22,6 +22,7 @@ dtos.Parameters = {
sigWindow: Number,
sigValidity: Number,
sigQty: Number,
idtyWindow: Number,
xpercent: Number,
msValidity: Number,
stepMax: Number,
......
......@@ -157,6 +157,7 @@ var tasks = {
async.apply(simpleInteger, "Maximum age of a non-written certification", "sigWindow", conf),
async.apply(simpleInteger, "Certification validity duration", "sigValidity", conf),
async.apply(simpleInteger, "Number of valid certifications required to be a member", "sigQty", conf),
async.apply(simpleInteger, "Maximum age of a non-written identity", "idtyWindow", conf),
async.apply(simpleFloat, "Percentage of sentries to be reached to match WoT distance rule", "xpercent", conf),
async.apply(simpleInteger, "Membership validity duration", "msValidity", conf),
async.apply(simpleInteger, "Number of blocks on which is computed median time", "medianTimeBlocks", conf),
......
......@@ -418,14 +418,15 @@ function BlockchainService () {
theConf.sigWindow = parseInt(sp[5]);
theConf.sigValidity = parseInt(sp[6]);
theConf.sigQty = parseInt(sp[7]);
theConf.xpercent = parseFloat(sp[8]);
theConf.msValidity = parseInt(sp[9]);
theConf.stepMax = parseInt(sp[10]);
theConf.medianTimeBlocks = parseInt(sp[11]);
theConf.avgGenTime = parseInt(sp[12]);
theConf.dtDiffEval = parseInt(sp[13]);
theConf.blocksRot = parseInt(sp[14]);
theConf.percentRot = parseFloat(sp[15]);
theConf.idtyWindow = parseFloat(sp[8]);
theConf.xpercent = parseFloat(sp[9]);
theConf.msValidity = parseInt(sp[10]);
theConf.stepMax = parseInt(sp[11]);
theConf.medianTimeBlocks = parseInt(sp[12]);
theConf.avgGenTime = parseInt(sp[13]);
theConf.dtDiffEval = parseInt(sp[14]);
theConf.blocksRot = parseInt(sp[15]);
theConf.percentRot = parseFloat(sp[16]);
theConf.currency = block.currency;
return theConf;
}
......
......@@ -59,6 +59,7 @@ program
.option('--sigPeriod <timestamp>', 'Minimum delay between 2 certifications of a same issuer, in seconds.')
.option('--sigStock <count>', 'Maximum quantity of valid certifications per member.')
.option('--sigWindow <duration>', 'Maximum age of a non-written certification.')
.option('--idtyWindow <duration>', 'Maximum age of a non-written certification.')
.option('--sigValidity <timestamp>', 'Validity duration of a certification, in seconds.')
.option('--msValidity <timestamp>', 'Validity duration of a memberships, in seconds.')
.option('--sigQty <number>', 'Minimum number of required certifications to be a member/stay as a member')
......@@ -600,6 +601,7 @@ function commandLineConf(conf) {
sigPeriod: program.sigPeriod,
sigStock: program.sigStock,
sigWindow: program.sigWindow,
idtyWindow: program.idtyWindow,
sigValidity: program.sigValidity,
sigQty: program.sigQty,
msValidity: program.msValidity,
......@@ -636,6 +638,7 @@ function commandLineConf(conf) {
if (cli.ucp.sigPeriod) conf.sigPeriod = cli.ucp.sigPeriod;
if (cli.ucp.sigStock) conf.sigStock = cli.ucp.sigStock;
if (cli.ucp.sigWindow) conf.sigWindow = cli.ucp.sigWindow;
if (cli.ucp.idtyWindow) conf.idtyWindow = cli.ucp.idtyWindow;
if (cli.ucp.sigValidity) conf.sigValidity = cli.ucp.sigValidity;
if (cli.ucp.msValidity) conf.msValidity = cli.ucp.msValidity;
if (cli.ucp.sigQty) conf.sigQty = cli.ucp.sigQty;
......
......@@ -629,6 +629,7 @@ The synchronization parameters.
sigWindow: 604800,
sigValidity: 2629800,
sigQty: 3,
idtyWindow: 604800,
xpercent: 5,
msValidity: 2629800,
stepMax: 3,
......
......@@ -822,7 +822,7 @@ To be a valid, a block must match the following rules:
* `Transactions` is a multiline field composed of [compact transactions](#compact-format)
* `Parameters` is a simple line field, composed of 1 float, 12 integers and 1 last float all separated by a colon `:`, and representing [currency parameters](#protocol-parameters) (a.k.a Protocol parameters, but valued for a given currency) :
c:dt:ud0:sigPeriod:sigStock:sigWindow:sigValidity:sigQty:xpercent:msValidity:stepMax:medianTimeBlocks:avgGenTime:dtDiffEval:blocksRot:percentRot
c:dt:ud0:sigPeriod:sigStock:sigWindow:sigValidity:sigQty:idtyWindow:xpercent:msValidity:stepMax:medianTimeBlocks:avgGenTime:dtDiffEval:blocksRot:percentRot
The document must be ended with a `BOTTOM_SIGNATURE` [Signature](#signature).
......@@ -924,6 +924,7 @@ sigStock | Maximum quantity of active certifications made by member.
sigWindow | Maximum delay a certification can wait before being expired for non-writing.
sigValidity | Maximum age of a active signature (in seconds)
sigQty | Minimum quantity of signatures to be part of the WoT
idtyWindow | Maximum delay an identity can wait before being expired for non-writing.
xpercent | Minimum percent of sentries to reach to match the distance rule
msValidity | Maximum age of an active membership (in seconds)
stepMax | Maximum distance between each WoT member and a newcomer
......@@ -1074,6 +1075,12 @@ Age is defined as the number of seconds between the certification's or membershi
AGE = current_time - block_time
###### Identity writability
An identity is to be considered *non-writable* if its age is less or equal to `[idtyWindow]`:
VALID = AGE <= [idtyWindow]
EXPIRED = AGE > [idtyWindow]
###### Certification writability
A certification is to be considered *non-writable* if its age is less or equal to `[sigWindow]`:
......@@ -1164,6 +1171,7 @@ We define `PPowMin` as the `PowMin` value of previous block.
##### Identity
* An identity must be writable to be included in the block.
* The blockchain cannot contain two or more identities sharing a same `USER_ID`.
* The blockchain cannot contain two or more identities sharing a same `PUBLIC_KEY`.
* Block#0's identities' `BLOCK_UID` must be the special value `0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855`.
......
......@@ -80,6 +80,7 @@ function Server (dbConf, overrideConf) {
sigValidity: constants.CONTRACT.DEFAULT.SIGVALIDITY,
msValidity: constants.CONTRACT.DEFAULT.MSVALIDITY,
sigQty: constants.CONTRACT.DEFAULT.SIGQTY,
idtyWindow: constants.CONTRACT.DEFAULT.IDTYWINDOW,
xpercent: constants.CONTRACT.DEFAULT.X_PERCENT,
percentRot: constants.CONTRACT.DEFAULT.PERCENTROT,
blocksRot: constants.CONTRACT.DEFAULT.BLOCKSROT,
......
......@@ -39,15 +39,17 @@ module.exports = {
"Currency: bb\n" +
"Number: 0\n" +
"PoWMin: 0\n" +
"Time: 1454866363\n" +
"MedianTime: 1454866363\n" +
"Time: 1458828976\n" +
"MedianTime: 1458828976\n" +
"Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" +
"Parameters: 0.007376575:100:157680000:0:40:3600:31536000:1:0.9:10000:3:20:960:10:20:0.6666666666666666\n" +
"MembersCount: 2\n" +
"Parameters: 0.007376575:2629800:100:0:40:604800:31536000:1:604800:0.9:31536000:3:20:960:10:20:0.6666666666666666\n" +
"MembersCount: 3\n" +
"Identities:\n" +
"HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:5PmGBvNj8AZ1T75Fe1rDLKy8lygwTFbrSwLYfMZS8eASxig5uHxx7P9l/hVgjIx7byPAkAsmrZIbYp/DEdnnDA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" +
"DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:/FZ6zVzAw0qZ9qD67CesQTRSp5glmooF37Dxs6kRHOOGZnh4ICykG07/FB76Z3C4H9tq1Qq5Hwbxw96+9Qj1CA==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tic\n" +
"DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo:bQAaenbeQk89bcKHHi7XsJGyo3mOZXNIphFqSjcJxp/a85k9vOF+yS4T18ZYV3rShI2QV6W7JlLPc4q+YdWhDw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" +
"Joiners:\n" +
"DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo:RkJsHDZdz++fFjr7+Qfv0pkSsTxkpD0TKW410XXVCNrPqHOPMaPVGauy6f1V0LuzVOJIRYPhDVekQLIcyEbjDw==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:toc\n" +
"HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:ICfYCQvs33HQhusMRswIFljGRjUIcmZPu+pt9qTcGEUf8/wZlIbiY/dwV6RUa4tI6TbvGcg2HUlmKLhFg9AKBQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:cat\n" +
"DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:njph4Y7Kn6vmycTp/rJplRj7PZVFiXv7YjZlC3mrSyXzvQNtX4JFAwXivsRDL6HcWnDesBqwEdrDAmiD28DNDQ==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:tic\n" +
"Actives:\n" +
......@@ -55,12 +57,13 @@ module.exports = {
"Revoked:\n" +
"Excluded:\n" +
"Certifications:\n" +
"DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:SC5FYPT8w2s8Yjd9BxgvN+5nTpPcNq7VkVxi9xIMer60Vi30eyWa3UYJdwW4B1nfjERqb9bqma9V3nchcdOCCg==\n" +
"HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo:0:X8P6NZNWq9qTmobhoFB4ITrSZQbEqAxkPt2wRpXC8JVniP3LvQi1h8DyiRvE6SbF1pyUsgRHiVKq1iB32YAGAA==\n" +
"DKpQPUL4ckzXYdnDRvCRKAm1gNvSdmAXnTrJZ7LvM5Qo:HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:0:BXksBR6BU3b694HuLoyUzoDd5xjdaJfYOY4EO7xSD/UkktW5oKy709RL/nCHY5vfPA0HrwPyi8vXAVKNzmGUCQ==\n" +
"HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:0:CStF7zf3SShRaW+E3YlU7iJNlMt78m/DDn2eoZZNfHLMwd0hqkBmjQWdVKcnJS3oHqiiFCnVIRAbF03cDlafCA==\n" +
"Transactions:\n" +
"InnerHash: F64B6514DCE5609ED98ED5B4F5F327B201F3FB2476E6766836F23DB60F9C2D85\n" +
"InnerHash: C88A6F36959002E64ECA3612B4E2BE5350FE845204F0B49BFE59ABA666AF0FC3\n" +
"Nonce: 1\n" +
"79uDgVhlOB5PX4iVzsm1UAZd8KiTY+sTQapaSUB0RV2pV0ncKTxPngeQ5mX0raHTzzdIRasx8EkawjJraBngBg==\n",
"+iDt5V9pGg6OI9qfeUh9fgsoZgsgRO/uHjz4jaKPU72xK9hoAL8NH+SrMsfD2m0yweJh8gQV4k1nPDEBrHs2Aw==\n",
WRONG_PROOF_OF_WORK:
"Version: 2\n" +
......@@ -117,7 +120,7 @@ module.exports = {
"Time: 1411776000\n" +
"MedianTime: 1411776000\n" +
"Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" +
"Parameters: 0.7376575:100:157680000:0:40:7200:31536000:1:0.9:31536000:3:1:60:10:20:0.67\n" +
"Parameters: 0.7376575:100:157680000:0:40:7200:31536000:1:1000:0.9:31536000:3:1:60:10:20:0.67\n" +
"MembersCount: 3\n" +
"Identities:\n" +
"Joiners:\n" +
......
......@@ -18,7 +18,7 @@ var expectHttpCode = httpTest.expectHttpCode;
let WebSocket = require('ws');
require('../../app/lib/logger')().mute();
// require('../../app/lib/logger')().mute();
var MEMORY_MODE = true;
var commonConf = {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment