Mise à jour de GitLab prévue ce dimanche 6 décembre 2020 à partir de 9h00 CEST | GitLab upgrade planned this Sunday December 6th 2020 from 9:00 AM CEST

Commit c34598b0 authored by Cédric Moreau's avatar Cédric Moreau

`ucoind sync` command working again

parent 2dc4e55b
......@@ -147,6 +147,32 @@ module.exports.database = {
}
};
module.exports.openpgp = {
init: function (currency, conf, done) {
// Import PGP key
openpgp.keyring.importPrivateKey(conf.pgpkey, conf.pgppasswd);
if (!module.exports.fingerprint()) {
pgplogger.error("Wrong PGP key password.");
process.exit(1);
return;
}
done();
}
};
function initServices (currency, conf, done) {
// Init ALL services
service.init(openpgp, currency, conf);
// Load services contexts
service.load(done);
}
module.exports.services = {
init: initServices
};
module.exports.express = {
app: function (currency, conf, onLoaded) {
......@@ -166,16 +192,19 @@ module.exports.express = {
app.use(express.cookieParser('your secret here'));
app.use(express.session());
// Import PGP key
openpgp.keyring.importPrivateKey(conf.pgpkey, conf.pgppasswd);
if (!module.exports.fingerprint()) {
pgplogger.error("Wrong PGP key password.");
process.exit(1);
return;
}
// HTTP Signatures
httpgp(app, conf, function (err) {
async.series([
function (next) {
// OpenPGP functions
module.exports.openpgp.init(currency, conf, next);
},
function (next){
initServices(currency, conf, next);
},
function (next){
// HTTP Signatures
httpgp(app, conf, next);
},
], function(err) {
// HTTPGP OK?
if (err) {
......@@ -192,9 +221,6 @@ module.exports.express = {
app.use(express.errorHandler());
}
// Init ALL services
service.init(openpgp, currency, conf);
// Init Daemon
var daemon = require('./daemon');
daemon.init(conf, module.exports.fingerprint());
......@@ -273,6 +299,25 @@ module.exports.express = {
var SyncService = service.Sync;
async.waterfall([
function (next) {
if(conf.ipv4){
logger.info('Connecting on interface %s...', conf.ipv4);
http.createServer(app).listen(conf.port, conf.ipv4, function(){
logger.info('uCoin server listening on ' + conf.ipv4 + ' port ' + conf.port);
next();
});
}
else next();
},
function (next) {
if(conf.ipv6){
logger.info('Connecting on interface %s...', conf.ipv6);
http.createServer(app).listen(conf.port, conf.ipv6, function(){
logger.info('uCoin server listening on ' + conf.ipv6 + ' port ' + conf.port);
});
}
else next();
},
function (next) {
mongoose.model('Peer').find({ fingerprint: module.exports.fingerprint() }, next);
},
......@@ -311,7 +356,7 @@ module.exports.express = {
},
function (signature, next) {
signature = signature.substring(signature.indexOf('-----BEGIN PGP SIGNATURE'));
PeeringService.persistPeering(raw2 + signature, module.exports.publicKey(), next);
PeeringService.submit(raw2 + signature, module.exports.fingerprint(), next);
},
], function (err) {
next(err);
......@@ -321,11 +366,11 @@ module.exports.express = {
}
},
function (next){
// Load services contexts
service.load(next);
mongoose.model('Peer').getTheOne(module.exports.fingerprint(), next);
},
function (next){
function (peer, next){
// Set peer's statut to UP
PeeringService.peer(peer);
PeeringService.peer().status = 'UP';
PeeringService.peer().save(function (err) {
// Update it in memory
......@@ -333,25 +378,6 @@ module.exports.express = {
next(err);
});
},
function (next) {
if(conf.ipv4){
logger.debug('Connecting on interface %s...', conf.ipv4);
http.createServer(app).listen(conf.port, conf.ipv4, function(){
logger.debug('uCoin server listening on ' + conf.ipv4 + ' port ' + conf.port);
next();
});
}
else next();
},
function (next) {
if(conf.ipv6){
logger.debug('Connecting on interface %s...', conf.ipv6);
http.createServer(app).listen(conf.port, conf.ipv6, function(){
logger.debug('uCoin server listening on ' + conf.ipv6 + ' port ' + conf.port);
});
}
else next();
},
function (next) {
// Initialize managed keys
PeeringService.initKeys(next);
......@@ -370,12 +396,18 @@ module.exports.express = {
logger.info('Broadcasting UP/NEW signals...');
PeeringService.sendUpSignal(next);
},
function (next) {
// Create AM0 proposal if not existing
mongoose.model('Amendment').getTheOneToBeVoted(0, function (err, am) {
function (next){
mongoose.model('Amendment').current(function (err, am) {
next(null, am);
});
},
function (currentAM, next) {
var nextAMNumber = currentAM && currentAM.number + 1 || 0;
// Create NEXT AM proposal if not existing
mongoose.model('Amendment').getTheOneToBeVoted(nextAMNumber, function (err, am) {
if (err || !am) {
logger.info('Creating root AM proposal...');
SyncService.createNext(null, next);
logger.info('Creating next AM (#%d) proposal...', nextAMNumber);
SyncService.createNext(currentAM, next);
return;
}
next();
......
......@@ -7,6 +7,8 @@ var Amendment = mongoose.model('Amendment');
var PublicKey = mongoose.model('PublicKey');
var Merkle = mongoose.model('Merkle');
var Key = mongoose.model('Key');
var Membership = mongoose.model('Membership');
var Voting = mongoose.model('Voting');
var Transaction = mongoose.model('Transaction');
var THTEntry = mongoose.model('THTEntry');
var Peer = mongoose.model('Peer');
......@@ -24,8 +26,9 @@ var THTService = service.THT;
var PeeringService = service.Peering;
var StrategyService = service.Strategy;
var ParametersService = service.Parameters;
var SyncService = service.Sync;
module.exports = function Synchroniser (host, port, authenticated, pgp, currency, conf) {
module.exports = function Synchroniser (host, port, authenticated, currency, conf) {
var that = this;
this.remoteFingerprint = null;
......@@ -53,7 +56,7 @@ module.exports = function Synchroniser (host, port, authenticated, pgp, currency
// Peer
//============
function (next){
node.ucg.peering.peer(next);
node.ucg.peering.get(next);
},
function (json, next){
remotePeer.copyValuesFrom(json);
......@@ -152,13 +155,12 @@ module.exports = function Synchroniser (host, port, authenticated, pgp, currency
err.split('\n').forEach(function (msg) {
logger.warn(msg);
});
remoteCurrentNumber = -1;
next(null, -2);
next();
return;
}
remoteCurrentNumber = parseInt(json.number);
amendments[remoteCurrentNumber] = json.raw;
var toGetNumbers = _.range(number, remoteCurrentNumber);
var toGetNumbers = _.range(number, remoteCurrentNumber + 1);
async.forEachSeries(toGetNumbers, function(amNumber, callback){
async.waterfall([
function (cb){
......@@ -169,45 +171,25 @@ module.exports = function Synchroniser (host, port, authenticated, pgp, currency
},
function (am, cb){
amendments[amNumber] = am.raw;
node.hdc.amendments.promoted(amNumber + 1, cb);
node.hdc.amendments.promoted(amNumber, cb);
},
function (am, cb){
amendments[amNumber + 1] = am.raw;
amendments[amNumber] = am.raw;
cb();
},
function (cb) {
node.hdc.amendments.view.signatures(amNumber + 1, sha1(amendments[amNumber + 1]).toUpperCase(), { leaves: true }, cb);
node.hdc.amendments.view.signatures(amNumber, sha1(amendments[amNumber]).toUpperCase(), { leaves: true }, cb);
},
function (json, cb){
applyVotes(amendments, amNumber, number, json, node, cb);
},
function (nextNumber, cb) {
number = nextNumber;
cb();
}
], function (err, result) {
callback(err);
});
}, function(err, result){
next(err, number);
});
});
},
function (number, next) {
if(number == remoteCurrentNumber){
// Synchronise remote's current
async.waterfall([
function (callback){
node.hdc.amendments.currentVotes({ leaves: true }, callback);
},
function (json, callback) {
applyVotes(amendments, number, number, json, node, callback);
}
], function (err) {
next(err);
});
}
else next();
});
},
//==============
......@@ -233,9 +215,9 @@ module.exports = function Synchroniser (host, port, authenticated, pgp, currency
var rm = new NodesMerkle(json);
if(rm.root() != merkle.root()){
var leavesToAdd = [];
node.ucg.tht.get({ extract: true }, function (err, json) {
node.ucg.tht.get({ leaves: true }, function (err, json) {
_(json.leaves).forEach(function(leaf){
if(merkle.leaves().indexOf(leaf.hash) == -1){
if(merkle.leaves().indexOf(leaf) == -1){
leavesToAdd.push(leaf);
}
});
......@@ -243,7 +225,7 @@ module.exports = function Synchroniser (host, port, authenticated, pgp, currency
async.forEachSeries(leavesToAdd, function(leaf, callback){
async.waterfall([
function (cb){
node.ucg.tht.get({ "leaf": leaf }, next);
node.ucg.tht.get({ "leaf": leaf }, cb);
},
function (json, cb){
var jsonEntry = json.leaf.value.entry;
......@@ -252,8 +234,6 @@ module.exports = function Synchroniser (host, port, authenticated, pgp, currency
["version", "currency", "fingerprint", "hosters", "trusts"].forEach(function (key) {
entry[key] = jsonEntry[key];
});
},
function (cb){
logger.info('THT entry %s', jsonEntry.fingerprint);
THTService.submit(entry.getRaw() + sign, cb);
}
......@@ -278,9 +258,9 @@ module.exports = function Synchroniser (host, port, authenticated, pgp, currency
var rm = new NodesMerkle(json);
if(rm.root() != merkle.root()){
var leavesToAdd = [];
node.ucg.peering.peers.get({ extract: true }, function (err, json) {
node.ucg.peering.peers.get({ leaves: true }, function (err, json) {
_(json.leaves).forEach(function(leaf){
if(merkle.leaves().indexOf(leaf.hash) == -1){
if(merkle.leaves().indexOf(leaf) == -1){
leavesToAdd.push(leaf);
}
});
......@@ -288,17 +268,16 @@ module.exports = function Synchroniser (host, port, authenticated, pgp, currency
async.forEachSeries(leavesToAdd, function(leaf, callback){
async.waterfall([
function (cb) {
node.ucg.peering.peers.get({ "leaf": leaf }, next);
node.ucg.peering.peers.get({ "leaf": leaf }, cb);
},
function (json, cb) {
var jsonEntry = json.leaf.value;
var sign = json.leaf.value.signature;
var entry = new Peer({});
["version", "currency", "fingerprint", "dns", "ipv4", "ipv6", "port"].forEach(function (key) {
["version", "currency", "fingerprint", "endpoints"].forEach(function (key) {
entry[key] = jsonEntry[key];
});
},
function (cb) {
entry.signature = sign;
ParametersService.getPeeringEntryFromRaw(entry.getRaw(), sign, cb);
},
function (rawSigned, keyID, cb){
......@@ -316,6 +295,91 @@ module.exports = function Synchroniser (host, port, authenticated, pgp, currency
else next();
});
},
//===========
// Registry
//===========
function (next){
Amendment.current(function (err, am) {
if (!am) {
next();
return;
}
async.waterfall([
function (next){
Key.getMembers(next);
},
function (keys, next) {
async.forEach(keys, function(member, callback){
async.waterfall([
function (next){
node.ucs.community.members.current(member.fingerprint, next);
},
function (membership, next){
logger.info('Membership of %s', member.fingerprint);
var ms = new Membership({
"version": membership.membership.version,
"currency": membership.membership.currency,
"issuer": membership.membership.issuer,
"membership": membership.membership.membership,
"type": "MEMBERSHIP"
});
ms.signature = membership.signature;
ParametersService.getMembership({
body: {
membership: ms.getRaw(),
signature: membership.signature
}
}, next);
},
function (ms, next){
ms.amNumber = am.number - 1;
ms.current = true;
ms.save(function (err) {
next(err);
});
},
], callback);
}, next);
},
function (next){
Key.getVoters(next);
},
function (keys, next) {
async.forEach(keys, function(member, callback){
async.waterfall([
function (next){
node.ucs.community.voters.current(member.fingerprint, next);
},
function (voting, next){
logger.info('Voting of %s', member.fingerprint);
var vt = new Voting({
"version": voting.voting.version,
"currency": voting.voting.currency,
"issuer": voting.voting.issuer,
"type": "VOTING"
});
vt.signature = voting.signature;
ParametersService.getVoting({
body: {
voting: vt.getRaw(),
signature: voting.signature
}
}, next);
},
function (voting, next){
voting.amNumber = am.number - 1;
voting.current = true;
voting.save(function (err) {
next(err);
});
},
], callback);
}, next);
},
], next);
})
},
], function (err, result) {
logger.info('Sync finished.');
done(err);
......@@ -372,10 +436,8 @@ module.exports = function Synchroniser (host, port, authenticated, pgp, currency
return;
}
async.waterfall([
function (next){
remoteMerkleFunc.call(remoteMerkleFunc, keyFingerprint, { leaves: false }, next);
},
function (json, onEveryTransactionProcessed){
function (onEveryTransactionProcessed){
var json = results.remote;
var transactions = {};
var numbers = _.range(json.leavesCount);
async.forEachSeries(numbers, function(number, onSentTransactionsProcessed){
......@@ -451,25 +513,38 @@ module.exports = function Synchroniser (host, port, authenticated, pgp, currency
}
function applyVotes(amendments, amNumber, number, json, node, cb) {
// logger.info('Applying votes for amendment #%s', amNumber);
// logger.info("Signatures: %s", _(json.leaves).size());
logger.info('Applying votes for amendment #%s', amNumber);
logger.info("Signatures: %s", _(json.leaves).size());
async.forEachSeries(json.leaves, function(leaf, callback){
async.waterfall([
function (next){
var hash = sha1(amendments[amNumber]).toUpperCase();
node.hdc.amendments.votes.of(amNumber, hash, { "leaf": leaf }, next);
node.hdc.amendments.view.signatures(amNumber, hash, { "leaf": leaf }, next);
},
function (json, next){
var vote = json.leaf;
VoteService.submit(amendments[amNumber] + vote.value.signature, function (err, am) {
// Promotion time
StrategyService.tryToPromote(am, function (err) {
if(!err)
number++;
next(err);
});
});
ParametersService.getVote({
body: {
amendment: amendments[amNumber],
signature: vote.value.signature
}
}, next);
},
function (vote, next){
VoteService.submit(vote, function (err, am) {
if(!err)
number++;
next(err);
});
// VoteService.submit(amendments[amNumber] + vote.value.signature, function (err, am) {
// // Promotion time
// StrategyService.tryToPromote(am, function (err) {
// if(!err)
// number++;
// next(err);
// });
// });
}
], callback);
}, function(err, result){
cb(err, number);
......
......@@ -209,23 +209,15 @@ AmendmentSchema.statics.nextNumber = function (done) {
AmendmentSchema.statics.current = function (done) {
this.find({ promoted: true }, function (err, amends) {
this.find({ promoted: true }).sort({ number: -1 }).limit(1).exec(function (err, amends) {
if(amends && amends.length == 1){
done(err, amends[0]);
return;
}
if(!amends || amends.length == 0){
else {
done('No current amendment');
return;
}
if(amends || amends.length > 1){
var current = undefined;
amends.forEach(function (am) {
if(!current || (current && current.number < am.number))
current = am;
});
done(err, current);
}
});
};
......
......@@ -64,10 +64,13 @@ function PeeringService(pgp, currency, conf) {
dbPeers.forEach(function(peer){
that.addPeer(peer);
});
Peer.getTheOne(that.cert.fingerprint, next);
Peer.getTheOne(that.cert.fingerprint, function (err, selfPeer) {
if (selfPeer)
peer = selfPeer;
next();
});
},
function (selfPeer, next){
peer = selfPeer;
function (next){
logger.debug('Loaded service: Peering');
next();
},
......@@ -105,7 +108,7 @@ function PeeringService(pgp, currency, conf) {
next(null, pubkey.raw);
},
function (pubkey, next){
that.persistPeering(signedPR, pubkey, next);
persistPeering(signedPR, pubkey, next);
}
], callback);
}
......@@ -149,14 +152,14 @@ function PeeringService(pgp, currency, conf) {
wasStatus = peer.status;
peer.setStatus(status.status, next);
peer.statusSigDate = status.sigDate;
peers[peer.fingerprint].status = status;
}
], function (err) {
peers[peer.fingerprint].status = status;
callback(err, status, peer, wasStatus);
});
}
this.persistPeering = function (signedPR, pubkey, done) {
function persistPeering (signedPR, pubkey, done) {
var peer = new Peer();
async.waterfall([
function (next){
......@@ -679,7 +682,7 @@ function PeeringService(pgp, currency, conf) {
function getForwardPeers (done) {
async.waterfall([
async.apply(Forward.find.bind(Forward), { to: this.cert.fingerprint }),
async.apply(Forward.find.bind(Forward), { to: that.cert.fingerprint }),
function (fwds, next) {
var fingerprints = _(fwds).map(function(fwd){ return fwd.fingerprint; });
Peer.getList(fingerprints, next);
......
......@@ -101,7 +101,55 @@ module.exports.get = function (pgp, currency, conf) {
}, next);
},
function (next){
SyncService.createNext(am, next);
Key.getMembers(next);
},
function (members, next){
// Update Merkle of proposed members
async.waterfall([
function (next){
Merkle.proposedMembers(next);
},
function (merkle, next){
var fingerprints = [];
members.forEach(function(m){
fingerprints.push(m.fingerprint);
});
fingerprints.sort();
merkle.initialize(fingerprints);
merkle.save(function (err) {
next(err);
});
},
], next);
},
function (next){
Key.getVoters(next);
},
function (voters, next){
// Update Merkle of proposed voters
async.waterfall([
function (next){
Merkle.proposedVoters(next);
},
function (merkle, next){
var fingerprints = [];
voters.forEach(function(v){
fingerprints.push(v.fingerprint);
});
fingerprints.sort();
merkle.initialize(fingerprints);
merkle.save(function (err) {
next(err);
});
},
], next);
},
function (next){
if (conf.createNext) {
SyncService.createNext(am, next);
} else {
next();
}
},
], cb);
}, done);
......
......@@ -454,9 +454,9 @@ module.exports.get = function (pgp, currency, conf) {
}
function updateUniversalDividend (amNext, amCurrent, done) {
// Time for Universal Dividend
// Time for Universal Dividend (and we have members)
var delayPassedSinceRootAM = (amNext.generated - conf.sync.AMStart);
if (delayPassedSinceRootAM > 0 && delayPassedSinceRootAM % conf.sync.UDFreq == 0) {
if (delayPassedSinceRootAM > 0 && delayPassedSinceRootAM % conf.sync.UDFreq == 0 && amNext.membersCount > 0) {
async.waterfall([
function (next) {
Amendment.getPreviouslyPromotedWithDividend(next);
......@@ -799,11 +799,11 @@ module.exports.get = function (pgp, currency, conf) {
var stateFunc = async.apply(whatToDo.state[lastKeyState.toString()][statusTo.toString()] || doNothingWithState, key, statusTo);
if ((lastKeyState == 0 && statusTo == 1) || (lastKeyState == -1 && statusTo == 0)) {