From c10b286dc03a3df27c0035b31c084dac0fec0658 Mon Sep 17 00:00:00 2001
From: Benoit Lavenier <benoit.lavenier@e-is.pro>
Date: Wed, 9 Aug 2023 17:50:19 +0200
Subject: [PATCH] enh(network): Select only compatible peer, at startup (not
 expert mode) : 1.8.7+ and storage enable, and exclude 1.9.0* version
 enh(network): Log: display the PID in all console logs enh(settings): Display
 duniter peer path, in badge fix(expert): disable duniter latest release url,
 to avoid warning on version > 1.7.10

---
 www/js/controllers/network-controllers.js |  2 +-
 www/js/platform.js                        | 42 +++++++++++----------
 www/js/services/bma-services.js           | 45 +++++++++++++++++++----
 www/js/services/http-services.js          |  2 +-
 www/js/services/network-services.js       |  6 +--
 www/js/services/settings-services.js      |  5 ++-
 6 files changed, 69 insertions(+), 33 deletions(-)

diff --git a/www/js/controllers/network-controllers.js b/www/js/controllers/network-controllers.js
index d44cb3332..df86a0141 100644
--- a/www/js/controllers/network-controllers.js
+++ b/www/js/controllers/network-controllers.js
@@ -531,7 +531,7 @@ function PeerInfoPopoverController($scope, $q, csSettings, csCurrency, csHttp, B
       ])
       .then(function() {
         // Compare, to check if newer
-        if ($scope.formData.latestRelease && $scope.formData.software == 'duniter') {
+        if ($scope.formData.latestRelease && $scope.formData.software === 'duniter') {
           var compare = csHttp.version.compare($scope.formData.version, $scope.formData.latestRelease.version);
           $scope.formData.isPreRelease = compare > 0;
           $scope.formData.hasNewRelease = compare < 0;
diff --git a/www/js/platform.js b/www/js/platform.js
index a095574bc..0d8c9121b 100644
--- a/www/js/platform.js
+++ b/www/js/platform.js
@@ -206,6 +206,14 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']
           var consensusBlockNumber = peers.length ? peers[0].currentNumber : undefined;
           var consensusPeerCount = peers.length;
 
+          // Not enough synchronized peers found (e.g. an isolated peer). Should never occur.
+          if (!consensusPeerCount || (minConsensusPeerCount > 0 && consensusPeerCount < minConsensusPeerCount)) {
+            console.warn("[platform] Not enough BMA peers on the main consensus block: {0} found. Will peek another peer...".format(consensusPeerCount));
+            // Retry using another fallback peer
+            return checkBmaNodeAlive(false)
+              .then(checkBmaNodeSynchronized); // Loop
+          }
+
           // Filter compatible peers
           peers = peers && peers.reduce(function(res, peer) {
             if (!peer.compatible) return res;
@@ -215,26 +223,20 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']
 
           console.info("[platform] Found {0}/{1} BMA peers, synchronized and compatible, in {2}ms".format(peers.length, consensusPeerCount, Date.now() - now));
 
-          // Not enough synchronized peers found (e.g. an isolated peer). Should never occur.
-          if (!consensusPeerCount || (minConsensusPeerCount > 0 && consensusPeerCount < minConsensusPeerCount)) {
-            console.warn("[platform] Not enough BMA peers on the main consensus block: {0} found. Will peek another peer...".format(consensusPeerCount));
-            // Retry using another fallback peer
-            return checkBmaNodeAlive(false)
-              .then(checkBmaNodeSynchronized); // Loop
-          }
-
           // Try to find the current peer in synchronized peers
-          var synchronizedIndex = _.findIndex(peers, function(peer) {
-            return BMA.url === peer.url;
-          });
-          if (synchronizedIndex !== -1) peers.splice(synchronizedIndex, 1);
+          var synchronized = false;
+          peers = peers && _.filter(peers, function(peer) {
+            if (BMA.url !== peer.url) return true
+            synchronized = true;
+            return false;
+          })
 
           // Saving other peers to settings
           console.debug("[platform] Saving {0} BMA peers in settings, for a later use".format(peers.length));
           csSettings.data.network.peers = peers;
 
           // OK (current BMA node is sync and compatible): continue
-          if (synchronizedIndex !== -1) {
+          if (synchronized) {
             console.info("[platform] Default peer [{0}{1}] is eligible.".format(BMA.server, BMA.path));
             return true;
           }
@@ -244,7 +246,10 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']
             BMA.server,
             BMA.path,
             consensusBlockNumber));
-          return csCurrency.blockchain.current()
+          return csCurrency.blockchain.current() // Use currency, to fill the cache
+            .catch(function() {
+              return {number: 0};
+            })
             .then(function(block) {
               // OK: only few blocks late, so we keep it
               if (Math.abs(block.number - consensusBlockNumber) <= 2) {
@@ -264,15 +269,14 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']
               }
 
               // KO: peek another peer
-              var randomPeer = _.sample(peers);
-              var synchronizedNode = new Peer(randomPeer);
+              var randomSynchronizedPeer = _.sample(peers);
 
               // If Expert mode: ask user to select a node
               if (askUserConfirmation) {
-                return askUseFallbackNode(synchronizedNode, 'CONFIRM.USE_SYNC_FALLBACK_NODE');
+                return askUseFallbackNode(randomSynchronizedPeer, 'CONFIRM.USE_SYNC_FALLBACK_NODE');
               }
 
-              return synchronizedNode;
+              return randomSynchronizedPeer;
             })
             .then(function(node) {
               if (node === true) return true;
@@ -304,7 +308,7 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']
      */
     function askUseFallbackNode(fallbackNode, messageKey) {
 
-      var newUrl = csHttp.getUrl(fallbackNode.host, fallbackNode.port, fallbackNode.path, fallbackNode.useSsl);
+      var newUrl = fallbackNode.url || csHttp.getUrl(fallbackNode.host, fallbackNode.port, fallbackNode.path, fallbackNode.useSsl);
       var confirmMsgParams = {old: BMA.url, new: newUrl};
 
       messageKey = messageKey || 'CONFIRM.USE_FALLBACK_NODE';
diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js
index 8a2ed97d7..0c6c38a4f 100644
--- a/www/js/services/bma-services.js
+++ b/www/js/services/bma-services.js
@@ -2,7 +2,8 @@
 
 angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.settings.services'])
 
-.factory('BMA', function($q, $window, $rootScope, $timeout, csCrypto, Api, Device, UIUtils, csConfig, csSettings, csCache, csHttp) {
+.factory('BMA', function($q, $window, $rootScope, $timeout, $http,
+                         csCrypto, Api, Device, UIUtils, csConfig, csSettings, csCache, csHttp) {
   'ngInject';
 
   function BMA(host, port, path, useSsl, useCache, timeout) {
@@ -1072,13 +1073,24 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
 
     // Define get latest release (or fake function is no URL defined)
     var duniterLatestReleaseUrl = csSettings.data.duniterLatestReleaseUrl && csHttp.uri.parse(csSettings.data.duniterLatestReleaseUrl);
-    exports.raw.getLatestRelease = duniterLatestReleaseUrl ?
-      csHttp.getWithCache(duniterLatestReleaseUrl.host,
-        duniterLatestReleaseUrl.port,
-        "/" + duniterLatestReleaseUrl.pathname,
-        /*useSsl*/ (+(duniterLatestReleaseUrl.port) === 443 || duniterLatestReleaseUrl.protocol === 'https:' || that.forceUseSsl),
-        csCache.constants.LONG
-      ) :
+    exports.raw.getLatestRelease =
+      duniterLatestReleaseUrl ?
+        $q(function(resolve, reject) {
+          $http.get(csSettings.data.duniterLatestReleaseUrl, {
+            timeout: csConfig.timeout,
+            responseType: 'json',
+            headers: {
+              'X-Requested-With': 'XMLHttpRequest'
+            }
+          }).success(resolve).error(reject)
+        })
+      // csHttp.getWithCache(duniterLatestReleaseUrl.host,
+      //   duniterLatestReleaseUrl.port,
+      //   "/" + duniterLatestReleaseUrl.pathname,
+      //   /*useSsl*/ (+(duniterLatestReleaseUrl.port) === 443 || duniterLatestReleaseUrl.protocol === 'https:' || that.forceUseSsl),
+      //   csCache.constants.LONG
+      // )
+        :
       // No URL define: use a fake function
       function() {
         return $q.when();
@@ -1088,6 +1100,23 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
       return exports.raw.getLatestRelease()
         .then(function (json) {
           if (!json) return;
+
+          // Gitlab release.json (used since Duniter 1.8)
+          if (Array.isArray(json)) {
+            var releaseVersion = _.find(json, function(res) {
+              return res.tag&& res.description && res.description.contains(':white_check_mark: Release\n');
+            })
+            if (releaseVersion) {
+              var version = releaseVersion.tag.startsWith('v') ? releaseVersion.tag.substring(1) : releaseVersion.tag;
+              var url = (csSettings.data.duniterLatestReleaseUrl.endsWith('.json') ?
+                csSettings.data.duniterLatestReleaseUrl.substring(0, csSettings.data.duniterLatestReleaseUrl.length - 4) :
+                csSettings.data.duniterLatestReleaseUrl) + '/' + releaseVersion.tag;
+              return {
+                version: version,
+                url: url
+              }
+            }
+          }
           if (json.name && json.html_url) {
             return {
               version: json.name,
diff --git a/www/js/services/http-services.js b/www/js/services/http-services.js
index 341bfb875..63b674742 100644
--- a/www/js/services/http-services.js
+++ b/www/js/services/http-services.js
@@ -144,7 +144,7 @@ angular.module('cesium.http.services', ['cesium.cache.services'])
         };
 
         if (autoRefresh) { // redo the request if need
-          config.cache = csCache.get(cachePrefix, maxAge, function (key, value, done) {
+          config.cache = csCache.get(cachePrefix, maxAge, function(key, value, done) {
               console.debug('[http] Refreshing cache for {{0}} '.format(key));
               $http.get(key, config)
                 .success(function (data) {
diff --git a/www/js/services/network-services.js b/www/js/services/network-services.js
index c4cb2b89d..8b50baad9 100644
--- a/www/js/services/network-services.js
+++ b/www/js/services/network-services.js
@@ -240,7 +240,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services',
               // Exclude if too old peering document
               json.blockNumber = buidBlockNumber(json.block);
               if (json.blockNumber && json.blockNumber < data.minOnlineBlockNumber) {
-                console.debug("[network] [#{0}] Exclude a too old peering document, on pubkey {1}".format(pid, json.pubkey.substring(0,6)));
+                console.debug("[network] [#{0}] Exclude a too old peering document, on pubkey {1}".format(pid, json.pubkey.substring(0,8)));
                 return;
               }
 
@@ -268,7 +268,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services',
                   var currentNumber = buidBlockNumber(head.buid);
                   // Exclude if on a too old block
                   if (currentNumber && currentNumber < data.minOnlineBlockNumber) {
-                    console.debug("[network] [#{0}] Exclude a too old WS2P message, on pubkey {1}".format(pid, head.pubkey.substring(0,6)));
+                    console.debug("[network] [#{0}] Exclude a too old WS2P message, on pubkey {1}".format(pid, head.pubkey.substring(0,8)));
                     return;
                   }
 
@@ -1020,7 +1020,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services',
 
       // CHeck version compatible, from min version
      if (!peer.version || !csHttp.version.isCompatible(csSettings.data.minVersionAtStartup || csSettings.data.minVersion, peer.version) ||
-         // Exclude beta versions (1.9.0, 1.9.0-dev and 1.8.7-rc4)
+         // Exclude beta versions (1.9.0* and 1.8.7-rc*)
          peer.version.startsWith('1.9.0') || peer.version.startsWith('1.8.7-rc')
        ) {
         console.debug('[network] [#{0}] BMA endpoint [{1}] is EXCLUDED (incompatible version {2})'.format(data.pid, peer.getServer(), peer.version));
diff --git a/www/js/services/settings-services.js b/www/js/services/settings-services.js
index 53567f1c4..84594f2f4 100644
--- a/www/js/services/settings-services.js
+++ b/www/js/services/settings-services.js
@@ -80,7 +80,10 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config'])
     newIssueUrl: "https://git.duniter.org/clients/cesium-grp/cesium/issues/new",
     userForumUrl: "https://forum.monnaie-libre.fr",
     latestReleaseUrl: "https://api.github.com/repos/duniter/cesium/releases/latest",
-    duniterLatestReleaseUrl: "https://api.github.com/repos/duniter/duniter/releases/latest",
+    // FIXME: get release from gitlab
+    duniterLatestReleaseUrl: undefined, // disable for now
+    // "https://api.github.com/repos/duniter/duniter/releases/latest", // Github
+    // "https://git.duniter.org/nodes/typescript/duniter/-/releases.json" // Gitlab
     httpsMode: false
   },
   defaultSettings = angular.merge({
-- 
GitLab