Mise à jour de GitLab prévue ce samedi 8 mai 2021 à partir de 9h00 CET | GitLab upgrade planned this Saturday May 4th of 2021 from 9:00 AM CET

Commit 1bdc3ca4 authored by Cédric Moreau's avatar Cédric Moreau

TDD: Block:Global: joiner must not be outdistanced from the WoT

parent 34e2e364
var _ = require('underscore');
var async = require('async');
var crypto = require('./crypto');
var common = require('./common');
......@@ -185,7 +186,34 @@ function GlobalValidator (conf, dao) {
}
function checkJoinersAreNotOudistanced (block, done) {
done();
var wotPubkeys = [];
async.waterfall([
function (next){
dao.getMembers(next);
},
function (identities, next){
// Stacking WoT pubkeys
identities.forEach(function(idty){
wotPubkeys.push(idty.pubkey);
});
var newLinks = getNewLinks(block);
// Checking distance of each member against them
async.forEach(block.joiners, function(inlineMembership, callback){
var ms = Membership.fromInline(inlineMembership);
async.waterfall([
function (next){
isOver3Hops(ms.issuer, wotPubkeys, newLinks, dao, next);
},
function (outdistancedCount, next){
if (outdistancedCount.length > 0)
next('Joiner is outdistanced from WoT');
else
next();
},
], callback);
}, next);
},
], done);
}
}
......@@ -198,4 +226,133 @@ function getNewLinks (block) {
newLinks[cert.to].push(cert.from);
});
return newLinks;
}
function isOver3Hops (pubkey, ofMembers, newLinks, dao, done) {
var newCertifiers = newLinks[pubkey] || [];
var remainingKeys = ofMembers.slice();
// Without self
remainingKeys = _(remainingKeys).difference([pubkey]);
var dist1Links = [];
async.waterfall([
function (next){
// Remove direct links (dist 1)
remainingKeys = _(remainingKeys).difference(newCertifiers);
next();
},
function (next) {
if (remainingKeys.length > 0) {
async.waterfall([
function (next){
dao.getValidLinksTo(pubkey, next);
},
function (links, next){
dist1Links = [];
links.forEach(function(lnk){
dist1Links.push(lnk.source);
});
// Add new certifiers as distance 1 links
dist1Links = _(dist1Links.concat(newCertifiers)).uniq();
next();
},
], next);
}
else next();
},
function (next){
// Remove distance 2 links (those for whom new links make 1 distance)
var found = [];
if (remainingKeys.length > 0) {
async.forEachSeries(remainingKeys, function(member, callback){
// Exists distance 1 link?
async.detect(dist1Links, function (dist1member, callbackDist1) {
// Look in newLinks
var signatories = (newLinks[dist1member] || []);
if (~signatories.indexOf(member)) {
callbackDist1(true);
return;
}
// dist1member signed 'pubkey', so here we look for (member => dist1member => pubkey sigchain)
dao.getPreviousLinkFromTo(member, dist1member, function (err, links) {
if (links && links.length > 0) {
found.push(member);
callbackDist1(true);
}
else callbackDist1(false);
});
}, function (detected) {
if (detected)
found.push(member);
callback();
});
}, function(err){
remainingKeys = _(remainingKeys).difference(found);
next(err);
});
}
else next();
},
function (next){
// Remove distance 3 links (those for whom new links make 2 distance)
var found = [];
if (remainingKeys.length > 0) {
async.forEachSeries(remainingKeys, function(member, callback){
var dist2Links = [];
async.waterfall([
function (next){
// Step 1. Detect distance 1 members from current member (potential dist 2 from 'pubkey')
// Look in database
dao.getValidLinksFrom(member, function (err, links) {
dist2Links = [];
links.forEach(function(lnk){
dist2Links.push(lnk.source);
});
next(err);
});
// Look in newLinks
_(newLinks).keys().forEach(function(signed){
(newLinks[signed] || []).forEach(function(signatories){
if (~signatories.indexOf(member)) {
dist2Links.push(signed);
}
});
});
},
function (next){
// Step 2. Detect links between distance 2 & distance 1 members
async.detect(dist2Links, function (dist2member, callbackDist2) {
// Exists distance 1 link?
async.detect(dist1Links, function (dist1member, callbackDist1) {
// Look in newLinks
var signatories = (newLinks[dist1member] || []);
if (~signatories.indexOf(dist2member)) {
callbackDist1(true);
return;
}
// dist1member signed 'pubkey', so here we look for (member => dist1member => pubkey sigchain)
dao.getPreviousLinkFromTo(dist2member, dist1member, function (err, links) {
if (links && links.length > 0) {
callbackDist1(true);
}
else callbackDist1(false);
});
}, callbackDist2);
}, function (detected) {
if (detected)
found.push(member);
callback();
});
},
], callback);
}, function(err){
remainingKeys = _(remainingKeys).difference(found);
next(err);
});
}
else next();
},
], function (err) {
done(err, remainingKeys);
});
}
\ No newline at end of file
......@@ -680,4 +680,27 @@ module.exports = {
"F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU:1411844660:tY5J+g3sM421sx0WNUuESUL8Zz2BU0UbtXT+nRsTlYThaDubMg/GmhsxWa0ccRJcZvftEwpENtVjyd6hyPSQCw==\n" +
"Transactions:\n" +
"kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n",
OUTDISTANCED_JOINER:
"Version: 1\n" +
"Type: Block\n" +
"Currency: beta_brousouf\n" +
"Nonce: 11\n" +
"Number: 3\n" +
"Date: 1411776000\n" +
"ConfirmedDate: 1411776000\n" +
"Issuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\n" +
"PreviousHash: 15978746968DB6BE3CDAF243E372FEB35F7B0924\n" +
"PreviousIssuer: G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU\n" +
"MembersCount: 3\n" +
"Identities:\n" +
"F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:1V/QnQcnJtQSSvhOFBhl7kGXBea8gKEQ6iqPNCVb41yI9gN79XGtUeHhjlumhQkPeizlzpkcNBkL8bhokiNcBQ==:1411837457:SNOW\n" +
"Joiners:\n" +
"F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:ze+ftHWFLYmjfvXyrx4a15N2VQjf6oen8kkMiYNYrVllbpb5IUcb28CenlOQbVd9cZCNGSkTP7xP5bt8KAqUAw==:1411837462:1411837457:SNOW\n" +
"Leavers:\n" +
"Excluded:\n" +
"Certifications:\n" +
"HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd:F5PtTpt8QFYMGtpZaETygB2C2yxCSxH1UW1VopBNZ6qg:1411844659:kr2JA6wCGfbNKGpyM86BscsFk22aA9oiAon8mWRPl4G8UpJKZs3tjuPRAw5+04KLCRWl/TT1TumDCkeEjev7DA==\n" +
"Transactions:\n" +
"kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n",
};
......@@ -15,7 +15,7 @@ var conf = new Configuration({
sigQty: 1
});
describe("Block local coherence", function(){
describe("Block global coherence", function(){
it('a valid block should not have any error', validate(blocks.VALID_ROOT, function (err, done) {
should.not.exist(err);
......@@ -64,6 +64,12 @@ describe("Block local coherence", function(){
done();
}));
it('a block with at least one joiner outdistanced from WoT should fail', validate(blocks.OUTDISTANCED_JOINER, function (err, done) {
should.exist(err);
err.should.equal('Joiner is outdistanced from WoT');
done();
}));
});
function validate (raw, callback) {
......@@ -114,7 +120,15 @@ function BlockCheckerDao (block) {
this.isMember = function (pubkey, done) {
// No existing member
done(null, false);
if (block.number == 0)
done(null, false);
else {
var members = [
'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd',
'G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU',
];
done(null, ~members.indexOf(pubkey));
}
}
this.getPreviousLinkFor = function (from, to, done) {
......@@ -131,4 +145,24 @@ function BlockCheckerDao (block) {
this.getValidLinksTo = function (to, done) {
done(null, []);
}
this.getMembers = function (done) {
if (block.number == 0)
done(null, []);
else {
done(null, [
{ pubkey: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd' },
{ pubkey: 'G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU' },
]);
}
}
this.getPreviousLinkFromTo = function (from, to, done) {
done(null, []);
}
this.getValidLinksFrom = function (member, done) {
done(null, []);
}
}
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