diff --git a/Desktop/DesktopApp.js b/Desktop/DesktopApp.js index fc5396f93..329542347 100644 --- a/Desktop/DesktopApp.js +++ b/Desktop/DesktopApp.js @@ -24,20 +24,13 @@ exports.newDesktopApp = function newDesktopApp() { thisObject.p2pMetwork = SA.projects.network.modules.p2pMetwork.newNetworkModulesP2PNetwork() await thisObject.p2pMetwork.initialize('Network Client') /* - Here we will pick a Network Node from all users profiles available that do have a Network Node running. // TODO - In the meantime, we will assume that we have chosen the following Network Node to connect to. + Here we will pick a Network Node from all users profiles available that do have a Network Node running. */ - selectedNetworkNode = { - userProfileHandle: "Luis-Fernando-Molina", - blockchainAccount: "0xeBDCB7a73c4796ca9F025d005630eCe773dd9e54", - ranking: 0, - host: "localhost", - port: global.env.NETWORK_WEB_SOCKETS_INTERFACE_PORT - } + let selectedNetworkNode = thisObject.p2pMetwork.p2pNodesToConnect[0] /* This is the Web Sockets client that interacts with the Superalgos Network. */ - thisObject.webSocketsClient = SA.projects.network.modules.webSocketsAppClient.newNetworkModulesWebSocketsAppClient() + thisObject.webSocketsClient = SA.projects.network.modules.webSocketsNetworkClient.newNetworkModulesWebSocketsNetworkClient() await thisObject.webSocketsClient.initialize('Network Client', selectedNetworkNode) console.log('Desktop Client Connected to Network Node via Web Sockets ................... Connected to port ' + global.env.NETWORK_WEB_SOCKETS_INTERFACE_PORT) /* diff --git a/Projects/Network/SA/Modules/P2PNetwork.js b/Projects/Network/SA/Modules/P2PNetwork.js index 5f6a90bc2..61ae16c87 100644 --- a/Projects/Network/SA/Modules/P2PNetwork.js +++ b/Projects/Network/SA/Modules/P2PNetwork.js @@ -5,6 +5,7 @@ exports.newNetworkModulesP2PNetwork = function newNetworkModulesP2PNetwork() { */ let thisObject = { joinTheNetworkAsNetworkPeer: joinTheNetworkAsNetworkPeer, + p2pNodesToConnect: undefined, /* Framework Functions */ initialize: initialize, finalize: finalize @@ -13,28 +14,31 @@ exports.newNetworkModulesP2PNetwork = function newNetworkModulesP2PNetwork() { return thisObject function finalize() { - + thisObject.p2pNodesToConnect = undefined } async function initialize(callerRole) { - let p2pNodesToConnect = [] - /* - We will setup here the maps and arryas we will need to operate within the P2P Network. - */ - let thisP2PNodeId = SA.secrets.map.get(global.env.P2P_NETWORK_NODE_SIGNING_ACCOUNT).signingAccountChildId - for (let i = 0; i < SA.projects.network.globals.memory.arrays.P2P_NETWORK_NODES.length; i++) { - let p2pNetworkNode = SA.projects.network.globals.memory.arrays.P2P_NETWORK_NODES[i] - if (thisP2PNodeId !== p2pNetworkNode.node.id) { - p2pNodesToConnect.push(p2pNetworkNode) - } - } - switch (callerRole) { case 'Network Client': { + thisObject.p2pNodesToConnect = [] + + for (let i = 0; i < SA.projects.network.globals.memory.arrays.P2P_NETWORK_NODES.length; i++) { + let p2pNetworkNode = SA.projects.network.globals.memory.arrays.P2P_NETWORK_NODES[i] + thisObject.p2pNodesToConnect.push(p2pNetworkNode) + } break } case 'Network Peer': { + thisObject.p2pNodesToConnect = [] + + let thisP2PNodeId = SA.secrets.map.get(global.env.P2P_NETWORK_NODE_SIGNING_ACCOUNT).signingAccountChildId + for (let i = 0; i < SA.projects.network.globals.memory.arrays.P2P_NETWORK_NODES.length; i++) { + let p2pNetworkNode = SA.projects.network.globals.memory.arrays.P2P_NETWORK_NODES[i] + if (thisP2PNodeId !== p2pNetworkNode.node.id) { + thisObject.p2pNodesToConnect.push(p2pNetworkNode) + } + } break } } diff --git a/Projects/Network/SA/Modules/UserProfiles.js b/Projects/Network/SA/Modules/UserProfiles.js index 746912e69..8e473c7d6 100644 --- a/Projects/Network/SA/Modules/UserProfiles.js +++ b/Projects/Network/SA/Modules/UserProfiles.js @@ -69,9 +69,26 @@ exports.newNetworkModulesUserProfiles = function newNetworkModulesUserProfiles() /* If the Signing Account is for a P2P node, we will add the node to the array of available nodes at the p2p network. */ - if (signingAccount.signingAccountChild.type === "P2P Network Node") { + if ( + signingAccount.signingAccountChild.type === "P2P Network Node" && + signingAccount.signingAccountChild.config === undefined + ) { + let condig + try { + condig = JSON.parse(signingAccount.signingAccountChild.config) + } catch (err) { + console.log('P2P Network Node Config not in JSON format. userProfileHandle = ' + userHandle + ' NodeId = ' + signingAccount.signingAccountChild.id) + continue + } + if (config.host === undefined) { + continue + } + if (config.webSocketsPort === undefined) { + continue + } + p2pNetworkNode = SA.projects.network.modules.p2pMetworkNode.newNetworkModulesP2PNetworkNode() - p2pMetworkNode.initialize(signingAccount.signingAccountChild, userPofile) + p2pMetworkNode.initialize(signingAccount.signingAccountChild, userPofile) SA.projects.network.globals.memory.arrays.P2P_NETWORK_NODES.push(p2pNetworkNode) } } diff --git a/Projects/Network/SA/Modules/WebSocketsAppClient.js b/Projects/Network/SA/Modules/WebSocketsAppClient.js deleted file mode 100644 index 9d08ed187..000000000 --- a/Projects/Network/SA/Modules/WebSocketsAppClient.js +++ /dev/null @@ -1,255 +0,0 @@ -exports.newNetworkModulesWebSocketsAppClient = function newNetworkModulesWebSocketsAppClient() { - - let thisObject = { - sendMessage: sendMessage, - initialize: initialize, - finalize: finalize - } - - let socketClient - - let web3 - let called = {} - let onMessageFunctionsMap = new Map() - - return thisObject - - function finalize() { - socketClient.close() - socketClient = undefined - networkInterface = undefined - peerInterface = undefined - - web3 = undefined - called = undefined - onMessageFunctionsMap = undefined - } - - async function initialize(callerRole, p2pNetworkNode) { - - web3 = new SA.nodeModules.web3() - socketClient = new SA.nodeModules.ws('ws://' + p2pNetworkNode.host + ':' + p2pNetworkNode.port) - await setUpWebsocketClient(callerRole, p2pNetworkNode) - } - - async function setUpWebsocketClient(callerRole) { - - return new Promise(connectToNewtwork) - - function connectToNewtwork(resolve, reject) { - - try { - - socketClient.onopen = () => { onConnection() } - socketClient.onerror = err => { onError(err) } - - function onConnection() { - - handshakeProcedure() - - function handshakeProcedure() { - - let callerTimestamp - - stepOneRequest() - - function stepOneRequest() { - /* - Send Handshake Message Step One: - - At Step One we will just say hello, identify ourselves - as a Network Client, and send the Network Node our - User Profile Handle. - - This Handle will be signed by the Network Node to prove - it's ouwn identity, and later we will sign it's own handle - to prove ours. - */ - socketClient.onmessage = socketMessage => { stepOneResponse(socketMessage) } - - callerTimestamp = (new Date()).valueOf() - - let message = { - messageType: 'Handshake', - callerRole: callerRole, - callerProfileHandle: SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileHandle, - callerTimestamp: callerTimestamp, - step: 'One' - } - socketClient.send(JSON.stringify(message)) - } - - function stepOneResponse(socketMessage) { - let response = JSON.parse(socketMessage.data) - - if (response.result !== 'Ok') { - console.log('[ERROR] Web Sockets Client -> stepOneResponse -> response.message = ' + response.message) - reject() - return - } - - let signature = JSON.parse(response.signature) - called.blockchainAccount = web3.eth.accounts.recover(signature) - /* - We will check that the signature received produces a valid Blockchain Account. - */ - if (called.blockchainAccount === undefined) { - console.log('[ERROR] Web Sockets Client -> stepOneResponse -> Signature does not produce a valid Blockchain Account.') - reject() - return - } - /* - We will check that the blockchain account taken from the signature matches - the one we have on record for the user profile of the Network Node we are calling. - */ - if (called.blockchainAccount !== p2pNetworkNode.blockchainAccount) { - console.log('[ERROR] Web Sockets Client -> stepOneResponse -> The Network Node called does not have the expected Profile Handle.') - reject() - return - } - - let signedMessage = JSON.parse(signature.message) - /* - We will verify that the signature belongs to the signature.message. - To do this we will hash the signature.message and see if we get - the same hash of the signature. - */ - let hash = web3.eth.accounts.hashMessage(signature.message) - if (hash !== signature.messageHash) { - console.log('[ERROR] Web Sockets Client -> stepOneResponse -> signature.message Hashed Does Not Match signature.messageHash.') - reject() - return - } - /* - We will check that the Network Node that responded has the same User Profile Handle - that we have on record, otherwise something is wrong and we should not proceed. - */ - if (signedMessage.calledProfileHandle !== p2pNetworkNode.userProfileHandle) { - console.log('[ERROR] Web Sockets Client -> stepOneResponse -> The Network Node called does not have the expected Profile Handle.') - reject() - return - } - /* - We will check that the profile handle we sent to the Network Node, is returned at the - signed message, to avoid man in the middle attackts. - */ - if (signedMessage.callerProfileHandle !== SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileHandle) { - console.log('[ERROR] Web Sockets Client -> stepOneResponse -> The Network Node callerProfileHandle does not match my own userProfileHandle.') - reject() - return - } - /* - We will also check that the callerTimestamp we sent to the Network Node, is returned at the - signed message, also to avoid man in the middle attackts. - */ - if (signedMessage.callerTimestamp !== callerTimestamp) { - console.log('[ERROR] Web Sockets Client -> stepOneResponse -> The Network Node callerTimestamp does not match my own callerTimestamp.') - reject() - return - } - - /* - All validations passed, it seems we can continue with Step Two. - */ - stepTwoRequest(signedMessage) - } - - function stepTwoRequest(signedMessage) { - /* - Send Handshake Message Step Two: - - Here we will sign a message with the Network Node profile - handle and timestamp to prove our own identity. - */ - socketClient.onmessage = socketMessage => { stepTwoResponse(socketMessage) } - - let signature = web3.eth.accounts.sign(JSON.stringify(signedMessage), SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileHandle) - - let message = { - messageType: 'Handshake', - signature: JSON.stringify(signature), - step: 'Two' - } - socketClient.send(JSON.stringify(message)) - } - - function stepTwoResponse(socketMessage) { - let response = JSON.parse(socketMessage.data) - - if (response.result !== 'Ok') { - console.log('[ERROR] Web Sockets Client -> stepOneResponse -> response.message = ' + response.message) - reject() - return - } - /* - This was the end of the Handshake producere. We are connected to the - Network Node and from now on, all response messages will be received - at this following function. - */ - socketClient.onmessage = socketMessage => { onMenssage(socketMessage) } - resolve() - } - } - } - - function onError(err) { - console.log('[ERROR] Web Sockets Client -> onError -> err.message = ' + err.message) - console.log('[ERROR] Web Sockets Client -> onError -> err.stack = ' + err.stack) - } - - } catch (err) { - console.log('[ERROR] Web Sockets Client -> setUpWebsocketClient -> err.stack = ' + err.stack) - } - - } - } - - function sendMessage(message) { - - return new Promise(sendSocketMessage) - - function sendSocketMessage(resolve, reject) { - - if (socketClient.readyState !== 1) { // 1 means connected and ready. - console.log('[ERROR] Web Sockets Client -> sendMessage -> Cannot send message while connection is closed.') - reject('Websockets Connection Not Ready.') - return - } - - let socketMessage = { - messageId: SA.projects.foundations.utilities.miscellaneousFunctions.genereteUniqueId(), - messageType: 'Request', - payload: message - } - onMessageFunctionsMap.set(socketMessage.messageId, onMenssageFunction) - socketClient.send( - JSON.stringify(socketMessage) - ) - - function onMenssageFunction(response) { - try { - if (response.result === 'Ok') { - resolve(response.data) - } else { - console.log('[ERROR] Web Sockets Client -> onMenssageFunction -> response.message = ' + response.message) - reject(response.message) - } - } catch (err) { - callbackFunction = undefined - console.log('[ERROR] Web Sockets Client -> err.stack = ' + err.stack) - } - } - } - } - - function onMenssage(socketMessage) { - - let response = JSON.parse(socketMessage.data) - /* - We get the functioin that is going to resolve or reject the promise given. - */ - onMenssageFunction = onMessageFunctionsMap.get(response.messageId) - onMessageFunctionsMap.delete(response.messageId) - onMenssageFunction(response) - } -} \ No newline at end of file diff --git a/Projects/Network/NT/Modules/WebSocketsNetworkClient.js b/Projects/Network/SA/Modules/WebSocketsNetworkClient.js similarity index 89% rename from Projects/Network/NT/Modules/WebSocketsNetworkClient.js rename to Projects/Network/SA/Modules/WebSocketsNetworkClient.js index 89742008c..a41ef6eae 100644 --- a/Projects/Network/NT/Modules/WebSocketsNetworkClient.js +++ b/Projects/Network/SA/Modules/WebSocketsNetworkClient.js @@ -10,7 +10,6 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWeb let web3 let called = {} - let selectedNetworkNode // This is a Network Node we pick to try to connect to. let onMessageFunctionsMap = new Map() return thisObject @@ -26,27 +25,18 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWeb onMessageFunctionsMap = undefined } - async function initialize() { - /* - Here we will pick a Network Node from all users profiles available that do have a Network Node running. // TODO - In the meantime, we will assume that we have chosen the following Network Node to connect to. - */ + async function initialize(callerRole, p2pNetworkNode) { + web3 = new SA.nodeModules.web3() - selectedNetworkNode = { - userProfileHandle: "Luis-Fernando-Molina", - blockchainAccount: "0xeBDCB7a73c4796ca9F025d005630eCe773dd9e54", - ranking: 0, - host: "localhost", - port: global.env.NETWORK_WEB_SOCKETS_INTERFACE_PORT - } + let host = JSON.parse(p2pNetworkNode.node.config).host + let port = JSON.parse(p2pNetworkNode.node.config).webSocketsPort - socketClient = new SA.nodeModules.ws('ws://' + selectedNetworkNode.host + ':' + selectedNetworkNode.port) - - await setUpWebsocketClient() + socketClient = new SA.nodeModules.ws('ws://' + host + ':' + port) + await setUpWebsocketClient(callerRole, p2pNetworkNode) } - async function setUpWebsocketClient() { + async function setUpWebsocketClient(callerRole) { return new Promise(connectToNewtwork) @@ -85,8 +75,8 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWeb let message = { messageType: 'Handshake', - callerRole: 'Network Node', - callerProfileHandle: SA.secrets.map.get(global.env.P2P_NETWORK_NODE_SIGNING_ACCOUNT).userProfileHandle, + callerRole: callerRole, + callerProfileHandle: SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileHandle, callerTimestamp: callerTimestamp, step: 'One' } @@ -116,7 +106,7 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWeb We will check that the blockchain account taken from the signature matches the one we have on record for the user profile of the Network Node we are calling. */ - if (called.blockchainAccount !== selectedNetworkNode.blockchainAccount) { + if (called.blockchainAccount !== p2pNetworkNode.userProfile.blockchainAccount) { console.log('[ERROR] Web Sockets Client -> stepOneResponse -> The Network Node called does not have the expected Profile Handle.') reject() return @@ -138,7 +128,7 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWeb We will check that the Network Node that responded has the same User Profile Handle that we have on record, otherwise something is wrong and we should not proceed. */ - if (signedMessage.calledProfileHandle !== selectedNetworkNode.userProfileHandle) { + if (signedMessage.calledProfileHandle !== p2pNetworkNode.userProfile.userProfileHandle) { console.log('[ERROR] Web Sockets Client -> stepOneResponse -> The Network Node called does not have the expected Profile Handle.') reject() return @@ -147,7 +137,7 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWeb We will check that the profile handle we sent to the Network Node, is returned at the signed message, to avoid man in the middle attackts. */ - if (signedMessage.callerProfileHandle !== SA.secrets.map.get(global.env.P2P_NETWORK_NODE_SIGNING_ACCOUNT).userProfileHandle) { + if (signedMessage.callerProfileHandle !== SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileHandle) { console.log('[ERROR] Web Sockets Client -> stepOneResponse -> The Network Node callerProfileHandle does not match my own userProfileHandle.') reject() return @@ -177,7 +167,7 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWeb */ socketClient.onmessage = socketMessage => { stepTwoResponse(socketMessage) } - let signature = web3.eth.accounts.sign(JSON.stringify(signedMessage), SA.secrets.map.get(global.env.P2P_NETWORK_NODE_SIGNING_ACCOUNT).privateKey) + let signature = web3.eth.accounts.sign(JSON.stringify(signedMessage), SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileHandle) let message = { messageType: 'Handshake', diff --git a/Projects/ProjectsSchema.json b/Projects/ProjectsSchema.json index b281f405f..7417a6826 100644 --- a/Projects/ProjectsSchema.json +++ b/Projects/ProjectsSchema.json @@ -1376,12 +1376,6 @@ "propertyName": "webSocketsInterface", "functionName": "newNetworkModulesWebSocketsInterface", "fileName": "WebSocketsInterface.js" - }, - { - "name": "Web Sockets Network Client", - "propertyName": "webSocketsNetworkClient", - "functionName": "newNetworkModulesWebSocketsNetworkClient", - "fileName": "WebSocketsNetworkClient.js" } ], "utilities": [] @@ -1397,11 +1391,11 @@ ], "modules": [ { - "name": "Web Sockets App Client", - "propertyName": "webSocketsAppClient", - "functionName": "newNetworkModulesWebSocketsAppClient", - "fileName": "WebSocketsAppClient.js" - }, + "name": "Web Sockets Network Client", + "propertyName": "webSocketsNetworkClient", + "functionName": "newNetworkModulesWebSocketsNetworkClient", + "fileName": "WebSocketsNetworkClient.js" + } { "name": "User Profiles", "propertyName": "userProfiles",