From 74d9f4d93b76551305d08471a84a929e4f745300 Mon Sep 17 00:00:00 2001 From: blavenie <benoit.lavenier@e-is.pro> Date: Fri, 26 Aug 2016 14:57:28 +0200 Subject: [PATCH] - TX : fix #120 TX must not create output base lower than input - Account wizard : logout if failed - fix #98 --- www/js/controllers/home-controllers.js | 17 ++- www/js/controllers/wallet-controllers.js | 85 ++++-------- www/js/services/wallet-services.js | 168 ++++++++++++++++------- 3 files changed, 161 insertions(+), 109 deletions(-) diff --git a/www/js/controllers/home-controllers.js b/www/js/controllers/home-controllers.js index 257f56f9e..b47d7861d 100644 --- a/www/js/controllers/home-controllers.js +++ b/www/js/controllers/home-controllers.js @@ -114,8 +114,16 @@ function NewAccountModalController($scope, $state, UIUtils, CryptoUtils, Wallet, return; } + var onErrorLogout = function(message) { + return function(err) { + Wallet.logout() + .then(function(){ + UIUtils.onError(message)(err); + }); + } + } + UIUtils.loading.show(); - $scope.closeModal(); Wallet.login($scope.formData.username, $scope.formData.password) .then(function() { @@ -131,12 +139,15 @@ function NewAccountModalController($scope, $state, UIUtils, CryptoUtils, Wallet, // Send membership IN Wallet.membership.inside() .then(function() { + + $scope.closeModal(); + // Redirect to wallet $state.go('app.view_wallet'); }) - .catch(UIUtils.onError('ERROR.SEND_MEMBERSHIP_IN_FAILED')); + .catch(onErrorLogout('ERROR.SEND_MEMBERSHIP_IN_FAILED')); }) - .catch(UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')); + .catch(onErrorLogout('ERROR.SEND_IDENTITY_FAILED')); }) .catch(function(err) { UIUtils.loading.hide(); diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js index 1396eb18d..a89431c35 100644 --- a/www/js/controllers/wallet-controllers.js +++ b/www/js/controllers/wallet-controllers.js @@ -135,58 +135,6 @@ function WalletController($scope, $q, $ionicPopup, $timeout, $scope.registerForm = registerForm; }; - $scope.checkUidNotExists = function(uid, pubkey) { - return $q(function(resolve, reject) { - BMA.wot.lookup({ search: uid }) // search on uid - .then(function(res) { - var found = res.results && - res.results.length > 0 && - res.results.some(function(pub){ - return pub.uids && pub.uids.length > 0 && - pub.uids.some(function(idty) { - return ((idty.uid === uid) && // check Uid - (pub.pubkey !== pubkey || !idty.revoked)); // check pubkey - }); - }); - if (found) { // uid is already used : display a message and call failed callback - reject('ACCOUNT.NEW.MSG_UID_ALREADY_USED'); - } - else { - resolve(uid); - } - }) - .catch(function() { - resolve(uid); - }); - }); - }; - - $scope.checkPubkeyNotExists = function(uid, pubkey) { - return $q(function(resolve, reject) { - BMA.wot.lookup({ search: pubkey }) // search on pubkey - .then(function(res) { - var found = res.results && - res.results.length > 0 && - res.results.some(function(pub){ - return pub.pubkey === pubkey && - pub.uids && pub.uids.length > 0 && - pub.uids.some(function(idty) { - return (!idty.revoked); // excluded revoked uid - }); - }); - if (found) { // uid is already used : display a message and reopen the popup - reject('ACCOUNT.NEW.MSG_PUBKEY_ALREADY_USED'); - } - else { - resolve(uid); - } - }) - .catch(function() { - resolve(uid); - }); - }); - }; - // Ask uid $scope.showUidPopup = function() { return $q(function(resolve, reject) { @@ -231,16 +179,20 @@ function WalletController($scope, $q, $ionicPopup, $timeout, // Send self identity $scope.self= function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + } + $scope.showUidPopup() .then(function(uid) { UIUtils.loading.show(); Wallet.self(uid) .then(function() { - $scope.doUpdate(); + $scope.updateView(); + UIUtils.loading.hide(); }) .catch(function(err){ - UIUtils.loading.hide(); UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')(err) .then(function() { $scope.self(); // loop @@ -251,8 +203,16 @@ function WalletController($scope, $q, $ionicPopup, $timeout, // Send membership IN $scope.membershipIn= function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + } + var doMembershipIn = function(retryCount) { Wallet.membership.inside() + .then(function() { + $scope.updateView(); + UIUtils.loading.hide(); + }) .catch(function(err) { if (!retryCount || retryCount <= 2) { $timeout(function() { @@ -260,7 +220,10 @@ function WalletController($scope, $q, $ionicPopup, $timeout, }, 1000); } else { - UIUtils.onError('ERROR.SEND_MEMBERSHIP_IN_FAILED')(err); + UIUtils.onError('ERROR.SEND_MEMBERSHIP_IN_FAILED')(err) + .then(function() { + $scope.membershipIn(); // loop + }); } }); }; @@ -276,7 +239,12 @@ function WalletController($scope, $q, $ionicPopup, $timeout, .then(function() { doMembershipIn(); }) - .catch(UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')); + .catch(function(err){ + UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')(err) + .then(function() { + $scope.membershipIn(); // loop + }); + }); } else { doMembershipIn(); @@ -292,6 +260,11 @@ function WalletController($scope, $q, $ionicPopup, $timeout, // Send membership IN $scope.membershipOut = function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + } + // TODO Add confirmation message + UIUtils.loading.show(); Wallet.membership.out() .catch(UIUtils.onError('ERROR.SEND_MEMBERSHIP_OUT_FAILED')); diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index a26a55fb8..fefbdb3e1 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -717,16 +717,18 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser maxBase: block.unitbase + 1, sources : [] }; + + // Get inputs, starting to use current base sources var amountBase = 0; while (inputs.amount < amount && amountBase <= block.unitbase) { - - // Get inputs, starting to use current base sources inputs = getInputs(amount, block.unitbase); - // Reduce amount (remove last digits) - amountBase++; - if (inputs.amount < amount && amountBase <= block.unitbase) { - amount = truncBase(amount, amountBase); + if (inputs.amount < amount) { + // try to reduce amount (replace last digits to zero) + amountBase++; + if (amountBase <= block.unitbase) { + amount = truncBase(amount, amountBase); + } } } @@ -763,11 +765,17 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser } return; } - if (amountBase > 0) { + // Avoid to get outputs on lower base + if (amountBase < inputs.minBase && !isBase(amount, inputs.minBase)) { + amount = truncBase(amount, inputs.minBase); console.debug("[wallet] Amount has been truncate to " + amount); } + else if (amountBase > 0) { + console.debug("[wallet] Amount has been truncate to " + amount); + } + - var tx = 'Version: 3\n' + + var tx = 'Version: 3\n' + 'Type: Transaction\n' + 'Currency: ' + data.currency + '\n' + 'Blockstamp: ' + block.number + '-' + block.hash + '\n' + @@ -852,59 +860,119 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser }); }, + checkUidNotExists = function(uid, pubkey) { + return $q(function(resolve, reject) { + BMA.wot.lookup({ search: uid }) // search on uid + .then(function(res) { + var found = res.results && + res.results.length > 0 && + res.results.some(function(pub){ + return pub.uids && pub.uids.length > 0 && + pub.uids.some(function(idty) { + return ((idty.uid === uid) && // check Uid + (pub.pubkey !== pubkey || !idty.revoked)); // check pubkey + }); + }); + if (found) { // uid is already used : display a message and call failed callback + reject({message: 'ACCOUNT.NEW.MSG_UID_ALREADY_USED'}); + } + else { + resolve(uid); + } + }) + .catch(function() { + resolve(uid); // not found, so OK + }); + }); + }, + + checkPubkeyNotExists = function(uid, pubkey) { + return $q(function(resolve, reject) { + BMA.wot.lookup({ search: pubkey }) // search on pubkey + .then(function(res) { + var found = res.results && + res.results.length > 0 && + res.results.some(function(pub){ + return pub.pubkey === pubkey && + pub.uids && pub.uids.length > 0 && + pub.uids.some(function(idty) { + return (!idty.revoked); // excluded revoked uid + }); + }); + if (found) { // uid is already used : display a message and reopen the popup + reject('ACCOUNT.NEW.MSG_PUBKEY_ALREADY_USED'); + } + else { + resolve(uid); + } + }) + .catch(function() { + resolve(uid); // not found, so OK + }); + }); + }, + /** * Send self identity */ - self = function(uid, requirements) { + self = function(uid, needToLoadRequirements) { return $q(function(resolve, reject) { if (!BMA.regex.USER_ID.test(uid)){ reject({message:'ERROR.INVALID_USER_ID'}); return; } - loadParameters() - .then(function() { + var block; + var identity; + $q.all([ + // check uid used by another pubkey + checkUidNotExists(uid, data.pubkey), + + // Load parameters (need to known the currency) + loadParameters(), + + // Get th current block BMA.blockchain.current() - .then(function (block) { - // Create identity to sign - var identity = 'Version: 2\n' + - 'Type: Identity\n' + - 'Currency: ' + data.currency + '\n' + - 'Issuer: ' + data.pubkey + '\n' + - 'UniqueID: ' + uid + '\n' + - 'Timestamp: ' + block.number + '-' + block.hash + '\n'; - - CryptoUtils.sign(identity, data.keypair) - .then(function (signature) { - var signedIdentity = identity + signature + '\n'; - // Send signed identity - BMA.wot.add({identity: signedIdentity}) - .then(function (result) { - if (!!requirements) { - // Refresh membership data - loadRequirements() - .then(function () { - resolve(); - }).catch(function (err) { - reject(err); - }); - } - else { - data.uid = uid; - data.blockUid = block.number + '-' + block.hash; - resolve(); - } - }) - .catch(function (err) { - if (err && err.ucode === BMA.errorCodes.IDENTITY_SANDBOX_FULL) { - reject({ucode: BMA.errorCodes.IDENTITY_SANDBOX_FULL, message: 'ERROR.IDENTITY_SANDBOX_FULL'}); - return; - } - reject(err); - }); + .then(function(current) { + block = current; + }) + ]) + // Create identity document to sign + .then(function() { + identity = 'Version: 2\n' + + 'Type: Identity\n' + + 'Currency: ' + data.currency + '\n' + + 'Issuer: ' + data.pubkey + '\n' + + 'UniqueID: ' + uid + '\n' + + 'Timestamp: ' + block.number + '-' + block.hash + '\n'; + + return CryptoUtils.sign(identity, data.keypair); + }) + // Add signature + .then(function (signature) { + var signedIdentity = identity + signature + '\n'; + // Send to node + return BMA.wot.add({identity: signedIdentity}) + .then(function (result) { + if (!!needToLoadRequirements) { + // Refresh membership data (if need) + loadRequirements() + .then(function () { + resolve(); }).catch(function (err) { reject(err); }); - }).catch(function (err) { + } + else { + data.uid = uid; + data.blockUid = block.number + '-' + block.hash; + resolve(); + } + }) + .catch(function (err) { + if (err && err.ucode === BMA.errorCodes.IDENTITY_SANDBOX_FULL) { + reject({ucode: BMA.errorCodes.IDENTITY_SANDBOX_FULL, message: 'ERROR.IDENTITY_SANDBOX_FULL'}); + return; + } reject(err); }); }).catch(function (err) { @@ -944,7 +1012,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser resolve(); }) .catch(function(err){reject(err);}); - }, 200); + }, 1000); // waiting for node to process membership doc }).catch(function(err){reject(err);}); }).catch(function(err){reject(err);}); }).catch(function(err){reject(err);}); -- GitLab