diff --git a/.gitignore b/.gitignore index 6f86d28b..ed976ac6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,16 @@ tests/thunder-tests/thunderActivity.db tests/thunder-tests/thunderclient.db tests/thunder-tests/thunderCollection.db tests/thunder-tests/thunderEnvironment.db +tests/thunder-tests/thunderActivity.json +tests/thunder-tests/thunderclient.json +tests/thunder-tests/thunderCollection.json +tests/thunder-tests/thunderEnvironment.json +tests/thunder-tests/backup/thunderActivity.db +tests/thunder-tests/backup/thunderclient.db +tests/thunder-tests/backup/thunderCollection.db +tests/thunder-tests/backup/thunderEnvironment.db +/target/ +.classpath +.project +.settings/org.eclipse.jdt.core.prefs +java-rubix-core.iml diff --git a/.idea/libraries/java_cid_v1_1_0.xml b/.idea/libraries/java_cid_v1_1_0.xml new file mode 100644 index 00000000..c5d600c5 --- /dev/null +++ b/.idea/libraries/java_cid_v1_1_0.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java-rubix-core.iml b/java-rubix-core.iml deleted file mode 100644 index d9323fbd..00000000 --- a/java-rubix-core.iml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/out/production/RubiX/com/rubix/AuthenticateNode/Authenticate.class b/out/production/RubiX/com/rubix/AuthenticateNode/Authenticate.class index 27d1a542..d2760882 100644 Binary files a/out/production/RubiX/com/rubix/AuthenticateNode/Authenticate.class and b/out/production/RubiX/com/rubix/AuthenticateNode/Authenticate.class differ diff --git a/out/production/RubiX/com/rubix/AuthenticateNode/SecretShare.class b/out/production/RubiX/com/rubix/AuthenticateNode/SecretShare.class index 21da112d..4de8cb69 100644 Binary files a/out/production/RubiX/com/rubix/AuthenticateNode/SecretShare.class and b/out/production/RubiX/com/rubix/AuthenticateNode/SecretShare.class differ diff --git a/out/production/RubiX/com/rubix/AuthenticateNode/SplitShares.class b/out/production/RubiX/com/rubix/AuthenticateNode/SplitShares.class index f4b1264a..4b9c4911 100644 Binary files a/out/production/RubiX/com/rubix/AuthenticateNode/SplitShares.class and b/out/production/RubiX/com/rubix/AuthenticateNode/SplitShares.class differ diff --git a/out/production/RubiX/com/rubix/Consensus/InitiatorConsensus.class b/out/production/RubiX/com/rubix/Consensus/InitiatorConsensus.class index 5f2b7df0..6562a8e3 100644 Binary files a/out/production/RubiX/com/rubix/Consensus/InitiatorConsensus.class and b/out/production/RubiX/com/rubix/Consensus/InitiatorConsensus.class differ diff --git a/out/production/RubiX/com/rubix/Consensus/InitiatorProcedure.class b/out/production/RubiX/com/rubix/Consensus/InitiatorProcedure.class index bda14d24..1d3b0152 100644 Binary files a/out/production/RubiX/com/rubix/Consensus/InitiatorProcedure.class and b/out/production/RubiX/com/rubix/Consensus/InitiatorProcedure.class differ diff --git a/out/production/RubiX/com/rubix/Consensus/QuorumConsensus.class b/out/production/RubiX/com/rubix/Consensus/QuorumConsensus.class index 4164d1c6..7ddf5083 100644 Binary files a/out/production/RubiX/com/rubix/Consensus/QuorumConsensus.class and b/out/production/RubiX/com/rubix/Consensus/QuorumConsensus.class differ diff --git a/out/production/RubiX/com/rubix/Constants/ConsensusConstants.class b/out/production/RubiX/com/rubix/Constants/ConsensusConstants.class index dc8c2096..df227605 100644 Binary files a/out/production/RubiX/com/rubix/Constants/ConsensusConstants.class and b/out/production/RubiX/com/rubix/Constants/ConsensusConstants.class differ diff --git a/out/production/RubiX/com/rubix/Constants/IPFSConstants.class b/out/production/RubiX/com/rubix/Constants/IPFSConstants.class index 43da9c41..c30a5837 100644 Binary files a/out/production/RubiX/com/rubix/Constants/IPFSConstants.class and b/out/production/RubiX/com/rubix/Constants/IPFSConstants.class differ diff --git a/out/production/RubiX/com/rubix/Resources/Functions.class b/out/production/RubiX/com/rubix/Resources/Functions.class index c6dc4ee9..2c107dc5 100644 Binary files a/out/production/RubiX/com/rubix/Resources/Functions.class and b/out/production/RubiX/com/rubix/Resources/Functions.class differ diff --git a/out/production/RubiX/com/rubix/Resources/IPFSNetwork.class b/out/production/RubiX/com/rubix/Resources/IPFSNetwork.class index c19d656e..c6c664b8 100644 Binary files a/out/production/RubiX/com/rubix/Resources/IPFSNetwork.class and b/out/production/RubiX/com/rubix/Resources/IPFSNetwork.class differ diff --git a/out/production/RubiX/com/rubix/SplitandStore/Recombine.class b/out/production/RubiX/com/rubix/SplitandStore/Recombine.class index 5495307b..a4d033e5 100644 Binary files a/out/production/RubiX/com/rubix/SplitandStore/Recombine.class and b/out/production/RubiX/com/rubix/SplitandStore/Recombine.class differ diff --git a/out/production/RubiX/com/rubix/SplitandStore/SeperateShares.class b/out/production/RubiX/com/rubix/SplitandStore/SeperateShares.class index e241e653..417bdbc2 100644 Binary files a/out/production/RubiX/com/rubix/SplitandStore/SeperateShares.class and b/out/production/RubiX/com/rubix/SplitandStore/SeperateShares.class differ diff --git a/out/production/RubiX/com/rubix/SplitandStore/Split.class b/out/production/RubiX/com/rubix/SplitandStore/Split.class index 2435dd20..8481de02 100644 Binary files a/out/production/RubiX/com/rubix/SplitandStore/Split.class and b/out/production/RubiX/com/rubix/SplitandStore/Split.class differ diff --git a/src/com/rubix/AuthenticateNode/Authenticate.java b/src/com/rubix/AuthenticateNode/Authenticate.java index 5218b56c..8f985043 100644 --- a/src/com/rubix/AuthenticateNode/Authenticate.java +++ b/src/com/rubix/AuthenticateNode/Authenticate.java @@ -42,38 +42,12 @@ public class Authenticate { public static boolean verifySignature(String detailString) throws IOException, JSONException { PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); - verifyCount++; IPFS ipfs = new IPFS("/ip4/127.0.0.1/tcp/" + IPFS_PORT); JSONObject details = new JSONObject(detailString); String decentralizedID = details.getString("did"); String hash = details.getString("hash"); - - String quorumSign; - String tokenSign; - String TIDSign; - JSONObject signs = new JSONObject(); - - if (details.optJSONObject(quorumSign) != null) { - - JSONObject signatureObject = details.getJSONObject("signatures"); - quorumSign = signatureObject.getString("QuorumSign"); - tokenSign = signatureObject.getString("TokenSign"); - TIDSign = signatureObject.getString("TIDSign"); - - signs.put(tokenSign, false); - signs.put(quorumSign, false); - signs.put(TIDSign, false); - - } else { - // make all three params in JSONObject signs as true - signs.put(quorumSign, false); - signs.put(tokenSign, true); - signs.put(TIDSign, true); - - quorumSign = details.getString("signature"); - } - + String signature = details.getString("signature"); syncDataTable(decentralizedID, null); String walletIdIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "didHash", decentralizedID); nodeData(decentralizedID, walletIdIpfsHash, ipfs); @@ -88,9 +62,9 @@ public static boolean verifySignature(String detailString) throws IOException, J JSONObject P = randomPositions("verifier", hash, 32, SenderSign); int[] posForSign = (int[]) P.get("posForSign"); int[] originalPos = (int[]) P.get("originalPos"); - for (int positionsLevelTwoTrail : posForSign) + for (int positionsLevelTwoTrail : posForSign) { senderWalletID.append(walletID.charAt(positionsLevelTwoTrail)); - + } String recombinedResult = PropImage.getpos(senderWalletID.toString(), signature); int[] positionsLevelZero = new int[32]; @@ -100,6 +74,7 @@ public static boolean verifySignature(String detailString) throws IOException, J StringBuilder decentralizedIDForAuth = new StringBuilder(); for (int value : positionsLevelZero) decentralizedIDForAuth.append(senderDIDBin.charAt(value)); + if (recombinedResult.equals(decentralizedIDForAuth.toString())) { return true; } else { diff --git a/src/com/rubix/Consensus/InitiatorConsensus.java b/src/com/rubix/Consensus/InitiatorConsensus.java index d030dcfa..df816187 100644 --- a/src/com/rubix/Consensus/InitiatorConsensus.java +++ b/src/com/rubix/Consensus/InitiatorConsensus.java @@ -1,10 +1,11 @@ package com.rubix.Consensus; +import static com.rubix.Constants.ConsensusConstants.INIT_HASH; import static com.rubix.Resources.Functions.DATA_PATH; import static com.rubix.Resources.Functions.LOGGER_PATH; import static com.rubix.Resources.Functions.QUORUM_COUNT; -import static com.rubix.Resources.Functions.checkTokenOwnershiByDID; import static com.rubix.Resources.Functions.getValues; +import static com.rubix.Resources.Functions.initHash; import static com.rubix.Resources.Functions.minQuorum; import static com.rubix.Resources.Functions.nodeData; import static com.rubix.Resources.Functions.syncDataTable; @@ -13,7 +14,6 @@ import static com.rubix.Resources.IPFSNetwork.swarmConnectP2P; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; @@ -22,7 +22,6 @@ import java.util.ArrayList; import com.rubix.AuthenticateNode.Authenticate; -import com.rubix.Resources.Functions; import com.rubix.Resources.IPFSNetwork; import org.apache.log4j.Logger; @@ -38,17 +37,13 @@ public class InitiatorConsensus { public static Logger InitiatorConsensusLogger = Logger.getLogger(InitiatorConsensus.class); public static volatile JSONObject quorumSignature = new JSONObject(); + public static volatile JSONArray signedAphaQuorumArray = new JSONArray(); private static final Object countLock = new Object(); private static final Object signLock = new Object(); public static ArrayList quorumWithShares = new ArrayList<>(); public static volatile int[] quorumResponse = { 0, 0, 0 }; public static volatile JSONArray finalQuorumSignsArray = new JSONArray(); - - /** - * Added by Anuradha K on 04/01/20222. - * To address SocketConnection reset Issue - */ - private static int socketTimeOut = 120000; + private static int socketTimeOut = 0; /** * This method increments the quorumResponse variable @@ -70,26 +65,6 @@ private static synchronized boolean voteNCount(int i, int quorumSize) { return status; } - /** - * This method increments the quorumResponse variable - */ - private static synchronized boolean selectStakingQuorum(String DID) { - boolean status; - PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); - synchronized (countLock) { - if (quorumResponse[i] < minQuorum(quorumSize)) { - quorumResponse[i]++; - InitiatorConsensusLogger.debug("quorum response added index " + i + " is " + quorumResponse[i] - + " quorumsize " + minQuorum(quorumSize)); - status = true; - } else { - status = false; - InitiatorConsensusLogger.debug("Staking Reached"); - } - } - return status; - } - /** * This method stores all the quorum signatures until required count for * consensus @@ -136,7 +111,6 @@ public static JSONObject start(String data, IPFS ipfs, int PORT, int index, Stri PrintStream[] qOut = new PrintStream[QUORUM_COUNT]; BufferedReader[] qIn = new BufferedReader[QUORUM_COUNT]; String[] quorumID = new String[QUORUM_COUNT]; - String[] signedAlphaQuorumID = new String[minQuorum(7)]; PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); JSONObject dataObject = new JSONObject(data); String hash = dataObject.getString("hash"); @@ -168,7 +142,6 @@ public static JSONObject start(String data, IPFS ipfs, int PORT, int index, Stri syncDataTable(null, quorumID[j]); String quorumDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", quorumID[j]); - String quorumWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "peerid", quorumID[j]); nodeData(quorumDidIpfsHash, quorumWidIpfsHash, ipfs); @@ -186,9 +159,9 @@ public static JSONObject start(String data, IPFS ipfs, int PORT, int index, Stri qOut[j].println(operation); if (operation.equals("new-credits-mining")) { - - // ? QST + credit info JSONObject qstDetails = dataObject.getJSONObject("qstDetails"); + qstDetails.put(INIT_HASH, initHash()); + // Verify QST Credits qOut[j].println(qstDetails.toString()); try { qResponse[j] = qIn[j].readLine(); @@ -198,9 +171,6 @@ public static JSONObject start(String data, IPFS ipfs, int PORT, int index, Stri } if (qResponse[j] != null) { if (qResponse[j].equals("Verified")) { - - // ! let all quorum mems know who is staking and use it in signature - detailsToken.put("stakingQuorumPeerID", quorumID[0]); qOut[j].println(detailsToken); try { qResponse[j] = qIn[j].readLine(); @@ -213,9 +183,8 @@ public static JSONObject start(String data, IPFS ipfs, int PORT, int index, Stri if (qResponse[j].equals("Auth_Failed")) { IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumID[j]); } else { - InitiatorConsensusLogger.trace( - "Signature Received from Q" + j + "(" + quorumID[j] + ") : " - + qResponse[j]); + InitiatorConsensusLogger.debug( + "Signature Received from " + quorumID[j] + " " + qResponse[j]); if (quorumResponse[index] > minQuorum(quorumSize)) { qOut[j].println("null"); IPFSNetwork @@ -234,6 +203,11 @@ public static JSONObject start(String data, IPFS ipfs, int PORT, int index, Stri if (quorumResponse[index] <= minQuorum(quorumSize) && voteStatus) { InitiatorConsensusLogger.debug( "waiting for " + quorumSize + " +signs " + role); + if (role.equals("alpha")) { + InitiatorConsensusLogger + .debug("Picking Quorum for Staking " + quorumID[j]); + signedAphaQuorumArray.put(quorumID[j]); + } while (quorumResponse[index] < minQuorum(quorumSize)) { } InitiatorConsensusLogger.debug("between Q1- to Q" + quorumSize @@ -268,6 +242,7 @@ public static JSONObject start(String data, IPFS ipfs, int PORT, int index, Stri } } } + } else if (qResponse[j].equals("440")) { InitiatorConsensusLogger.debug("Credit Verification failed: Duplicates found"); IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumID[j]); @@ -279,10 +254,11 @@ public static JSONObject start(String data, IPFS ipfs, int PORT, int index, Stri InitiatorConsensusLogger.debug("Credit Verification failed: Credits hash mismatch"); IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumID[j]); } else if (qResponse[j].equals("443")) { - InitiatorConsensusLogger.debug("Failed to initialize credit verification"); + InitiatorConsensusLogger.debug("Credit Verification failed: Init hash mismatch"); IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumID[j]); } } + } qOut[j].println(detailsToken); @@ -310,13 +286,18 @@ public static JSONObject start(String data, IPFS ipfs, int PORT, int index, Stri JSONObject detailsToVerify = new JSONObject(); detailsToVerify.put("did", didHash); detailsToVerify.put("hash", hash); - detailsToVerify.put("signatures", qResponse[j]); + detailsToVerify.put("signature", qResponse[j]); if (Authenticate.verifySignature(detailsToVerify.toString())) { InitiatorConsensusLogger.debug(role + " node authenticated at index " + index); boolean voteStatus = voteNCount(index, quorumSize); if (quorumResponse[index] <= minQuorum(quorumSize) && voteStatus) { InitiatorConsensusLogger .debug("waiting for " + quorumSize + " +signs " + role); + if (role.equals("alpha")) { + InitiatorConsensusLogger + .debug("Picking Quorum for Staking " + quorumID[j]); + signedAphaQuorumArray.put(quorumID[j]); + } while (quorumResponse[index] < minQuorum(quorumSize)) { } InitiatorConsensusLogger @@ -346,7 +327,6 @@ public static JSONObject start(String data, IPFS ipfs, int PORT, int index, Stri } } } - } catch (IOException | JSONException e) { IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumID[j]); InitiatorConsensusLogger.error("IOException Occurred"); @@ -356,79 +336,6 @@ public static JSONObject start(String data, IPFS ipfs, int PORT, int index, Stri quorumThreads[j].start(); } - if (operation.equals("new-credits-mining")) { - Thread[] stakingThreads = new Thread[signedAlphaQuorumID.length]; - // ? one of the validators stake 1 RBT and send the stake ID to the miner. - // choose a quorum member from 1 to 5 who have signed the transaction - for (int p = 0; p < signedAlphaQuorumID.length; p++) { - int s = p; - stakingThreads[p] = new Thread(() -> { - try { - InitiatorConsensusLogger.debug( - "Contacting Signed Alpha Quorum ID : " + signedAlphaQuorumID[s] - + " for staking. Index " - + s); - - qSocket[s] = new Socket("127.0.0.1", PORT + s); - qSocket[s].setSoTimeout(socketTimeOut); - qIn[s] = new BufferedReader(new InputStreamReader(qSocket[s].getInputStream())); - qOut[s] = new PrintStream(qSocket[s].getOutputStream()); - - qOut[s].println("stake-token"); - try { - qResponse[s] = qIn[s].readLine(); - String stakingQuorumDID = getValues(DATA_PATH + "DataTable.json", "didHash", - "peerid", signedAlphaQuorumID[s]); - if (checkTokenOwnershiByDID(qResponse[s], stakingQuorumDID)) { - if (true) { - - // ! generate stake ID and send to staking quorum - - InitiatorConsensusLogger.debug("Staking Successful at index " + s); - } else { - - InitiatorConsensusLogger.debug("sending null for slow quorum "); - qOut[s].println("null"); - IPFSNetwork.executeIPFSCommands( - "ipfs p2p close -t /p2p/" + signedAlphaQuorumID[s]); - - } - - } else { - - InitiatorConsensusLogger.debug("sending null for slow quorum "); - qOut[s].println("null"); - IPFSNetwork.executeIPFSCommands( - "ipfs p2p close -t /p2p/" + signedAlphaQuorumID[s]); - - } - } catch (SocketException e) { - InitiatorConsensusLogger - .warn("Alpha Quorum (for Staking)" + signedAlphaQuorumID[s] - + " is unable to Respond!"); - IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + signedAlphaQuorumID[s]); - } - - } catch (Exception e) { - InitiatorConsensusLogger.error("Exception Occurred"); - e.printStackTrace(); - } - }); - stakingThreads[s].start(); - } - // check the balance - // if balance is sufficient then stake the token - // else send a null to Qa(j) - // if Qa(j) sends a null then close the connection - // else send the stake ID to Qa(j) - // pin the stake ID (initiator) and keep it in a file for future use - File stakesFolder = new File(Functions.WALLET_DATA_PATH.concat("/Stakes")); - if (!stakesFolder.exists()) - stakesFolder.mkdirs(); - // send mining fee to Qa(j) - 0.02 RBT - // close the connection - } - while (quorumResponse[index] < minQuorum(quorumSize) || quorumSignature.length() < (minQuorum(alphaSize) + 2 * minQuorum(7))) { } diff --git a/src/com/rubix/Consensus/InitiatorProcedure.java b/src/com/rubix/Consensus/InitiatorProcedure.java index 142364e4..10557faf 100644 --- a/src/com/rubix/Consensus/InitiatorProcedure.java +++ b/src/com/rubix/Consensus/InitiatorProcedure.java @@ -3,6 +3,7 @@ import static com.rubix.Resources.Functions.LOGGER_PATH; import static com.rubix.Resources.Functions.calculateHash; import static com.rubix.Resources.Functions.getSignFromShares; +import static com.rubix.Resources.Functions.initHash; import static com.rubix.Resources.Functions.minQuorum; import java.io.IOException; @@ -33,6 +34,7 @@ public class InitiatorProcedure { * @param data Data required for hashing and signing * @param ipfs IPFS instance * @param PORT port for forwarding to quorum + * @throws IOException */ public static void consensusSetUp(String data, IPFS ipfs, int PORT, int alphaSize, String operation) throws JSONException { @@ -44,7 +46,6 @@ public static void consensusSetUp(String data, IPFS ipfs, int PORT, int alphaSiz String receiverDidIpfs = dataObject.getString("receiverDidIpfs"); String pvt = dataObject.getString("pvt"); String senderDidIpfs = dataObject.getString("senderDidIpfs"); - String initHash = dataObject.getString("initHash"); String token = dataObject.getString("token"); JSONArray alphaList = dataObject.getJSONArray("alphaList"); JSONArray betaList = dataObject.getJSONArray("betaList"); @@ -78,11 +79,10 @@ public static void consensusSetUp(String data, IPFS ipfs, int PORT, int alphaSiz senderSignQ = getSignFromShares(pvt, authSenderByQuorumHash); data1.put("sign", senderSignQ); data1.put("senderDID", senderDidIpfs); - data1.put("initHash", initHash); - data1.put("token", token); data1.put(ConsensusConstants.TRANSACTION_ID, tid); data1.put(ConsensusConstants.HASH, authSenderByQuorumHash); data1.put(ConsensusConstants.RECEIVERID, receiverDidIpfs); + data1.put(ConsensusConstants.INIT_HASH, initHash()); data2.put("Share1", Q1Share); data2.put("Share2", Q2Share); @@ -102,6 +102,9 @@ public static void consensusSetUp(String data, IPFS ipfs, int PORT, int alphaSiz JSONObject dataSend = new JSONObject(); dataSend.put("hash", authQuorumHash); dataSend.put("details", detailsForQuorum); + + InitiatorProcedureLogger.debug("hash"+authQuorumHash); + InitiatorProcedureLogger.debug("data1"+data1.toString()); if (operation.equals("new-credits-mining")) { JSONObject qstDetails = dataObject.getJSONObject("qstDetails"); diff --git a/src/com/rubix/Consensus/QuorumConsensus.java b/src/com/rubix/Consensus/QuorumConsensus.java index f581e1d3..524a92d2 100644 --- a/src/com/rubix/Consensus/QuorumConsensus.java +++ b/src/com/rubix/Consensus/QuorumConsensus.java @@ -1,9 +1,23 @@ package com.rubix.Consensus; +import static com.rubix.Constants.ConsensusConstants.INIT_HASH; +import static com.rubix.Constants.MiningConstants.MINED_RBT; +import static com.rubix.Constants.MiningConstants.MINED_RBT_SIGN; +import static com.rubix.Constants.MiningConstants.MINE_ID; +import static com.rubix.Constants.MiningConstants.MINE_ID_SIGN; +import static com.rubix.Constants.MiningConstants.MINE_TID; +import static com.rubix.Constants.MiningConstants.MINING_TID_SIGN; +import static com.rubix.Constants.MiningConstants.STAKED_QUORUM_DID; +import static com.rubix.Constants.MiningConstants.STAKED_TOKEN; +import static com.rubix.Constants.MiningConstants.STAKED_TOKEN_SIGN; +import static com.rubix.Constants.MiningConstants.STAKE_DATA; import static com.rubix.Resources.Functions.DATA_PATH; import static com.rubix.Resources.Functions.IPFS_PORT; import static com.rubix.Resources.Functions.LOGGER_PATH; +import static com.rubix.Resources.Functions.PAYMENTS_PATH; import static com.rubix.Resources.Functions.SYNC_IP; +import static com.rubix.Resources.Functions.TOKENCHAIN_PATH; +import static com.rubix.Resources.Functions.TOKENS_PATH; import static com.rubix.Resources.Functions.WALLET_DATA_PATH; import static com.rubix.Resources.Functions.calculateHash; import static com.rubix.Resources.Functions.deleteFile; @@ -12,13 +26,17 @@ import static com.rubix.Resources.Functions.getValues; import static com.rubix.Resources.Functions.initHash; import static com.rubix.Resources.Functions.nodeData; +import static com.rubix.Resources.Functions.readFile; +import static com.rubix.Resources.Functions.strToIntArray; import static com.rubix.Resources.Functions.syncDataTable; import static com.rubix.Resources.Functions.updateJSON; import static com.rubix.Resources.Functions.writeToFile; import static com.rubix.Resources.IPFSNetwork.add; import static com.rubix.Resources.IPFSNetwork.executeIPFSCommands; import static com.rubix.Resources.IPFSNetwork.listen; +import static com.rubix.Resources.IPFSNetwork.pin; +import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.FileWriter; @@ -32,8 +50,12 @@ import java.net.URL; import java.text.ParseException; import java.util.HashSet; +import java.util.Random; + +import javax.imageio.ImageIO; import com.rubix.AuthenticateNode.Authenticate; +import com.rubix.AuthenticateNode.PropImage; import com.rubix.Resources.Functions; import com.rubix.Resources.IPFSNetwork; @@ -74,10 +96,8 @@ public QuorumConsensus(String role, int port) { public void run() { while (true) { PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); - String peerID, transactionID, verifySenderHash, receiverDID, appName, initHash, senderPrivatePos, token, - stakingQuorumDID, - stakedToken, - senderDidIpfsHash = "", senderPID = ""; + String peerID, transactionID, verifySenderHash, receiverDID, appName, senderPrivatePos, + senderDidIpfsHash = "", senderPID = "", ownerHash = "", initHash = ""; ServerSocket serverSocket = null; Socket socket = null; try { @@ -107,48 +127,157 @@ public void run() { serverSocket.close(); executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); } + - if (operation.equals("stake-token")) { - - String stakeDetails; - - // ! send token ID choosen - out.println("null"); - + // ? staking logic starts here + if (operation.equals("new-credits-mining")) { + QuorumConsensusLogger.debug("New Credits"); + String getNewCreditsData = null; try { - stakeDetails = in.readLine(); + getNewCreditsData = in.readLine(); } catch (SocketException e) { - QuorumConsensusLogger.debug("Sender Input Stream Null - New stake ID Details"); + QuorumConsensusLogger.debug("Sender Input Stream Null - New Credits Details"); socket.close(); serverSocket.close(); executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); } - JSONObject stakeDetailsJSON = new JSONObject(stakeDetails); - generateStakeIDByToken(stakeDetailsJSON.getString("stakeID"), stakeDetailsJSON.getString("minedToken")); - out.println("OK") - // ! wait for 0.02 RBT + // Verify QST Credits + JSONObject qstObject = new JSONObject(getNewCreditsData); - } + if (qstObject.getString(INIT_HASH).equals(initHash())) { + + // Get level of token from advisory node + int creditsRequired = 0; + JSONObject resJsonData_credit = new JSONObject(); + String GET_URL_credit = SYNC_IP + "/getCurrentLevel"; + URL URLobj_credit = new URL(GET_URL_credit); + HttpURLConnection con_credit = (HttpURLConnection) URLobj_credit.openConnection(); + con_credit.setRequestMethod("GET"); + int responseCode_credit = con_credit.getResponseCode(); + System.out.println("GET Response Code :: " + responseCode_credit); + if (responseCode_credit == HttpURLConnection.HTTP_OK) { + BufferedReader in_credit = new BufferedReader( + new InputStreamReader(con_credit.getInputStream())); + String inputLine_credit; + StringBuffer response_credit = new StringBuffer(); + while ((inputLine_credit = in_credit.readLine()) != null) { + response_credit.append(inputLine_credit); + } + in_credit.close(); + // QuorumConsensusLogger.debug("response from service " + + // response_credit.toString()); + resJsonData_credit = new JSONObject(response_credit.toString()); + int level_credit = resJsonData_credit.getInt("level"); + creditsRequired = (int) Math.pow(2, (2 + level_credit)); + QuorumConsensusLogger.debug("credits required " + creditsRequired); + + } else + QuorumConsensusLogger.debug("GET request not worked"); + + // Level 1 Verification: Verify hash of n objects + JSONArray qstArray = qstObject.getJSONArray("qstArray"); + JSONArray creditsArray = qstObject.getJSONArray("credits"); + + boolean flag = true; + // if qstArray has any duplicate object + for (int i = 0; i < qstArray.length(); i++) { + for (int j = i + 1; j < qstArray.length(); j++) { + if (qstArray.getJSONObject(i).getString("credits") + .equals(qstArray.getJSONObject(j).getString("credits"))) { + flag = false; + break; + } + } + } + for (int i = 0; i < creditsRequired; i++) { + QuorumConsensusLogger.debug("Credit object: " + creditsArray.getJSONObject(i).toString()); + QuorumConsensusLogger.debug( + "Credit Hash: " + + calculateHash(creditsArray.getJSONObject(i).toString(), "SHA3-256")); + String reHash = calculateHash(qstArray.getJSONObject(i).getString("credits"), "SHA3-256"); + if (!reHash.equals(qstArray.getJSONObject(i).getString("creditHash"))) { + QuorumConsensusLogger.debug("Recalculation " + reHash + " - " + + qstArray.getJSONObject(i).getString("creditHash")); + flag = false; + } + } - if (operation.equals("new-credits-mining")) { + if (flag) { + boolean verifySigns = true; + for (int i = 0; i < creditsRequired; i++) { + if (!Authenticate.verifySignature(creditsArray.getJSONObject(i).toString())) + verifySigns = false; + } + if (verifySigns) { + HashSet hashSet = new HashSet(); + long startTime = System.currentTimeMillis(); + for (int i = 0; i < creditsArray.length(); i++) { + String sign = creditsArray.getJSONObject(i).getString("signature"); + String signHash = calculateHash(sign, "SHA3-256"); + hashSet.add(signHash); + } + long endTime = System.currentTimeMillis(); + QuorumConsensusLogger.debug("Total Time for HashSet: " + (endTime - startTime)); + if (hashSet.size() == qstArray.length() * 15) { + QuorumConsensusLogger.debug("Mining Verified"); + out.println("Verified"); + + } else { + QuorumConsensusLogger + .debug("HashSet: " + hashSet.size() + " QST Size " + qstArray.length()); + QuorumConsensusLogger.debug("Mining Not Verified: Duplicates Found"); + out.println("440"); + socket.close(); + serverSocket.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); + } + } else { + out.println("441"); + socket.close(); + serverSocket.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); + } + } else { + out.println("442"); + socket.close(); + serverSocket.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); + } + } else { + out.println("443"); + socket.close(); + serverSocket.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); + } + } + else if (operation.equals("alpha-stake-token")) { + + QuorumConsensusLogger.debug("Staking 1 RBT for incoming mining transaction..."); + String response = null; - QuorumConsensusLogger.debug("New Credits"); - String getNewCreditsData = null; try { - getNewCreditsData = in.readLine(); + // ! token hash just mined + response = in.readLine(); } catch (SocketException e) { QuorumConsensusLogger.debug("Sender Input Stream Null - New Credits Details"); socket.close(); serverSocket.close(); executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); } - // Verify QST Credits - JSONObject qstObject = new JSONObject(getNewCreditsData); - // Get level of token from advisory node - int creditsRequired = 0; - JSONObject resJsonData_credit = new JSONObject(); - String GET_URL_credit = SYNC_IP + "/getlevel"; + JSONObject genesisBlock = new JSONObject(response); + QuorumConsensusLogger.debug("Validating new token details: " + genesisBlock); + + boolean LEVEL_VALID = false; + boolean MINE_CREDIT_VALID = false; + + // ! check token is in same level + String TokenContent = genesisBlock.getString("tokenContent"); + String tokenLevel = TokenContent.substring(0, 3); + int tokenLevelInt = Integer.parseInt(tokenLevel); + int tokenLevelValue = (int) Math.pow(2, tokenLevelInt + 2); + + String GET_URL_credit = SYNC_IP + "/getCurrentLevel"; URL URLobj_credit = new URL(GET_URL_credit); HttpURLConnection con_credit = (HttpURLConnection) URLobj_credit.openConnection(); con_credit.setRequestMethod("GET"); @@ -163,239 +292,367 @@ public void run() { response_credit.append(inputLine_credit); } in_credit.close(); - QuorumConsensusLogger.debug("response from service " + response_credit.toString()); - resJsonData_credit = new JSONObject(response_credit.toString()); + // QuorumConsensusLogger.debug("response from service " + + // response_credit.toString()); + JSONObject resJsonData_credit = new JSONObject(response_credit.toString()); int level_credit = resJsonData_credit.getInt("level"); - creditsRequired = (int) Math.pow(2, (2 + level_credit)); - QuorumConsensusLogger.debug("credits required " + creditsRequired); + int creditsRequired = (int) Math.pow(2, (2 + level_credit)); + + if (level_credit == tokenLevelInt) { + + QuorumConsensusLogger.debug("Validated level of newly minted token"); + LEVEL_VALID = true; + } else { + QuorumConsensusLogger.debug("Invalid level of newly minted token"); + LEVEL_VALID = false; + } } else QuorumConsensusLogger.debug("GET request not worked"); - // Level 1 Verification: Verify hash of n objects - JSONArray qstArray = qstObject.getJSONArray("qstArray"); - JSONArray creditsArray = qstObject.getJSONArray("credits"); - - boolean flag = true; - for (int i = 0; i < creditsRequired; i++) { - QuorumConsensusLogger.debug("Credit object: " + creditsArray.getJSONObject(i).toString()); - QuorumConsensusLogger.debug( - "Credit Hash: " + calculateHash(creditsArray.getJSONObject(i).toString(), "SHA3-256")); - String reHash = calculateHash(qstArray.getJSONObject(i).getString("credits"), "SHA3-256"); - if (!reHash.equals(qstArray.getJSONObject(i).getString("creditHash"))) { - QuorumConsensusLogger.debug("Recalculation " + reHash + " - " - + qstArray.getJSONObject(i).getString("creditHash")); - flag = false; - } - } - if (flag) { + // ! validate mined token hash and ownership + if (genesisBlock.has("quorumSignatures")) { - boolean verifySigns = true; - for (int i = 0; i < creditsRequired; i++) { - if (!Authenticate.verifySignature(creditsArray.getJSONObject(i).toString())) - verifySigns = false; - } - if (verifySigns) { - HashSet hashSet = new HashSet(); - long startTime = System.currentTimeMillis(); - for (int i = 0; i < creditsArray.length(); i++) { - String sign = creditsArray.getJSONObject(i).getString("signature"); - String signHash = calculateHash(sign, "SHA3-256"); - hashSet.add(signHash); - } - long endTime = System.currentTimeMillis(); - QuorumConsensusLogger.debug("Total Time for HashSet: " + (endTime - startTime)); - if (hashSet.size() == qstArray.length() * 15) { - QuorumConsensusLogger.debug("Mining Verified"); - out.println("Verified"); + try { + int randomNumber = new Random().nextInt(15); + JSONObject genesisSignatures = genesisBlock.getJSONObject("quorumSignContent"); + JSONArray keys = genesisSignatures.names(); + String signer = keys.getString(randomNumber); + String signature = genesisSignatures.getString(signer); + + JSONObject VerificationPick = new JSONObject(); + VerificationPick.put("signature", signature); + VerificationPick.put("did", signer); + VerificationPick.put("hash", genesisBlock.getString("tid")); + + QuorumConsensusLogger.debug("Verifying credit signature of new token: " + VerificationPick); + + if (Authenticate.verifySignature(VerificationPick.toString())) { + + QuorumConsensusLogger.debug("Validated signature of newly minted token"); + MINE_CREDIT_VALID = true; } else { - QuorumConsensusLogger - .debug("HashSet: " + hashSet.size() + " QST Size " + qstArray.length()); - QuorumConsensusLogger.debug("Mining Not Verified: Duplicates Found"); - out.println("440"); - socket.close(); - serverSocket.close(); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); + QuorumConsensusLogger.debug("Signature not verified"); + MINE_CREDIT_VALID = false; } - } else { - out.println("441"); - socket.close(); - serverSocket.close(); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); + } catch (Exception e) { + QuorumConsensusLogger + .debug("Mined Token - Quorum Signature Hash not found. Skipping... Exception: " + + e.getMessage()); + MINE_CREDIT_VALID = false; } - } else { - out.println("442"); - socket.close(); - serverSocket.close(); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); - } - } else - QuorumConsensusLogger.debug("Old Credits Mining / Whole RBT Token Transfer"); - - String getRecData = null; - try { - getRecData = in.readLine(); - } catch (SocketException e) { - QuorumConsensusLogger.debug("Sender Input Stream Null - Ping Check / Receiver Details"); - socket.close(); - serverSocket.close(); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); - } - if (getRecData != null) { - if (getRecData.contains("ping check")) { - QuorumConsensusLogger.debug("Ping check from sender: " + getRecData); - out.println("pong response"); - } else { + } - QuorumConsensusLogger.debug("Received Details from initiator: " + getRecData); - readSenderData = new JSONObject(getRecData); - senderPrivatePos = readSenderData.getString("sign"); - senderDidIpfsHash = readSenderData.getString("senderDID"); - transactionID = readSenderData.getString("Tid"); - verifySenderHash = readSenderData.getString("Hash"); - receiverDID = readSenderData.getString("RID"); - - // ! additional info for the mining verification - initHash = readSenderData.getString("initHash"); - token = readSenderData.getString("token"); - stakedToken = readSenderData.getString("stakedToken"); - String stakingQuorumPeerID = readSenderData.getString("stakingQuorumPeerID"); - stakingQuorumDID = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", - stakingQuorumPeerID); - - // ! match initiator initHash with quorum. if didn't match, reject - - if (!initHash.equals(initHash())) { - QuorumConsensusLogger.debug("Initiator Hash Mismatch"); - out.println("443"); - socket.close(); - serverSocket.close(); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); - } + if (LEVEL_VALID) { + // LEVEL_VALID && MINE_CREDIT_VALID - syncDataTable(senderDidIpfsHash, null); + QuorumConsensusLogger.debug("Sending staking token details..."); + JSONArray tokenToStake = new JSONArray(); - senderPID = getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", senderDidIpfsHash); - String senderWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "didHash", - senderDidIpfsHash); + String bankFile = readFile(PAYMENTS_PATH.concat("BNK00.json")); + JSONArray bankArray = new JSONArray(bankFile); - nodeData(senderDidIpfsHash, senderWidIpfsHash, ipfs); + if (bankArray.length() > 0) { - // ! check if each quorum member is signing on the quorumHash (which now is - // sender + receiver hash) - // concat of sender hash and rec hash) + File tokenFile; + File tokenchainFile; + JSONObject bankObject = new JSONObject(); + String stakedTokenHash = ""; + boolean tokenAvailableToStake = false; + JSONArray stakedTokenChainArray = new JSONArray(); - String quorumHash = calculateHash(token + transactionID + stakingQuorumDID, "SHA3-256"); - String stakeHash = calculateHash(token + stakedToken, "SHA3-256"); + // for loop to check bankArray for token + for (int i = 0; i < bankArray.length(); i++) { - QuorumConsensusLogger.debug("1: " + verifySenderHash); - QuorumConsensusLogger.debug("2: " + receiverDID); - QuorumConsensusLogger.debug("Quorum hash: " + quorumHash); + bankObject = bankArray.getJSONObject(i); + stakedTokenHash = bankObject.getString("tokenHash"); - JSONObject detailsToVerify = new JSONObject(); - detailsToVerify.put("did", senderDidIpfsHash); - detailsToVerify.put("hash", verifySenderHash); - detailsToVerify.put("signature", senderPrivatePos); + tokenFile = new File(TOKENS_PATH + stakedTokenHash); + tokenchainFile = new File(TOKENCHAIN_PATH + stakedTokenHash + ".json"); - writeToFile(LOGGER_PATH + "tempverifysenderhash", verifySenderHash, false); - String verifySenderIPFSHash = IPFSNetwork.addHashOnly(LOGGER_PATH + "tempverifysenderhash", - ipfs); - deleteFile(LOGGER_PATH + "tempverifysenderhash"); + QuorumConsensusLogger.debug("Checking token" + stakedTokenHash + " for staking..."); - // QuorumConsensusLogger.debug("Checking providers for: " + verifySenderHash); - // ArrayList dhtOwnersList = dhtOwnerCheck(verifySenderHash); - // QuorumConsensusLogger.debug("Providers: " + dhtOwnersList); - // boolean consensusIDcheck = false; - // if(dhtOwnersList.size() <= 2 && dhtOwnersList.contains(senderPID)) - // consensusIDcheck = true; + if (tokenFile.exists() && tokenchainFile.exists()) { - if (Authenticate.verifySignature(detailsToVerify.toString())) { - QuorumConsensusLogger.debug("Quorum Authenticated Sender"); + String tokenChain = readFile(TOKENCHAIN_PATH + stakedTokenHash + ".json"); + stakedTokenChainArray = new JSONArray(tokenChain); + + if(stakedTokenChainArray.length() > 0) { + // get last object of tokenchainarray + JSONObject lastTokenChainObject = stakedTokenChainArray + .getJSONObject(stakedTokenChainArray.length() - 1); - QuorumConsensusLogger.debug("ConsensusID pass"); + if (!lastTokenChainObject.has(MINE_ID)) { + // && stakedTokenChainArray.length() > tokenLevelValue - // json obj called quorumSignss - JSONObject quorumSigns = new JSONObject(); + QuorumConsensusLogger.debug("Staking 1 RBT for incoming mining transaction..."); + tokenToStake.put(stakedTokenHash); + tokenToStake.put(stakedTokenChainArray); - // ! 1st sign: TID - String QuorumSignatureOne = getSignFromShares(DATA_PATH + didHash + "/PrivateShare.png", - transactionID); - quorumSigns.put("TIDSign", QuorumSignatureOne); - // ? - // ! 2st sign: Token - String QuorumSignatureTwo = getSignFromShares(DATA_PATH + didHash + "/PrivateShare.png", - token); - quorumSigns.put("TokenSign", QuorumSignatureTwo); + bankArray.remove(i); + bankArray.put(bankObject); + writeToFile(PAYMENTS_PATH.concat("BNK00.json"), bankArray.toString(), false); - // ! 3th sign: Token + TID - String QuorumSignatureFive = getSignFromShares(DATA_PATH + didHash + "/PrivateShare.png", - quorumHash); - quorumSigns.put("QuorumSign", QuorumSignatureFive); + tokenAvailableToStake = true; - out.println(quorumSigns); + break; + } + + } else { + + QuorumConsensusLogger.debug("Token Chain does not have enough height to pledge...Trying to pledge with another token!"); + } + } + } - String creditSignatures = null; - try { - creditSignatures = in.readLine(); - } catch (SocketException e) { - QuorumConsensusLogger.debug("Sender Input Stream Null - Credits"); + if (tokenAvailableToStake) { + + QuorumConsensusLogger.debug("Token and TokenChain files found"); + + String hashString = stakedTokenHash.concat(senderDidIpfsHash); + String hashForPositions = calculateHash(hashString, "SHA3-256"); + BufferedImage privateShare = ImageIO + .read(new File( + DATA_PATH.concat(didHash).concat("/PrivateShare.png"))); + String firstPrivate = PropImage.img2bin(privateShare); + int[] privateIntegerArray1 = strToIntArray(firstPrivate); + String privateBinary = Functions.intArrayToStr(privateIntegerArray1); + String positions = ""; + for (int j = 0; j < privateIntegerArray1.length; j += 49152) { + positions += privateBinary.charAt(j); + } + tokenToStake.put(positions); + // ! token which will be staked + out.println("tokenToStake"); + out.println(tokenToStake); + + try { + response = in.readLine(); + QuorumConsensusLogger + .debug("Staking response after verifying staked token: " + response); + } catch (SocketException e) { + QuorumConsensusLogger + .debug("Sender Input Stream Null - Stake Token Validation by Miner Failed"); + socket.close(); + serverSocket.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); + } + + if (response.equals("alpha-stake-token-verified")) { + + JSONObject stakingSigns = new JSONObject(); + // staker DID + stakingSigns.put(STAKED_QUORUM_DID, didHash); + // staked token and sign from staker + stakingSigns.put(STAKED_TOKEN, stakedTokenHash); + stakingSigns.put( + STAKED_TOKEN_SIGN, getSignFromShares(DATA_PATH + didHash + + "/PrivateShare.png", + stakedTokenHash)); + // tid and sign from staker + stakingSigns.put(MINE_TID, genesisBlock.getString("tid")); + stakingSigns.put( + MINING_TID_SIGN, + getSignFromShares(DATA_PATH + didHash + "/PrivateShare.png", + genesisBlock.getString("tid"))); + // mined token and sign from staker + stakingSigns.put(MINED_RBT, genesisBlock.getString("tokenHash")); + stakingSigns.put( + MINED_RBT_SIGN, getSignFromShares(DATA_PATH + didHash + "/PrivateShare.png", + genesisBlock.getString("tokenHash"))); + + genesisBlock.put(STAKE_DATA, stakingSigns); + + FileWriter shareWriter = new FileWriter(new File(LOGGER_PATH + "stake.txt"), + true); + shareWriter.write(genesisBlock.toString()); + shareWriter.close(); + File readStake = new File(LOGGER_PATH + "stake.txt"); + String mineID = add(readStake.toString(), ipfs); + pin(mineID, ipfs); + + File stakeFile = new File( + WALLET_DATA_PATH.concat("/Stake/").concat(mineID).concat(".json")); + if (!stakeFile.exists()) + stakeFile.createNewFile(); + writeToFile(stakeFile.toString(), genesisBlock.toString(), false); + + deleteFile(LOGGER_PATH + "stake.txt"); + + // mine ID + stakingSigns.put(MINE_ID, mineID); + stakingSigns.put(MINE_ID_SIGN, + getSignFromShares(DATA_PATH + didHash + "/PrivateShare.png", mineID)); + stakingSigns.put("sender", genesisBlock.getString("sender")); + + QuorumConsensusLogger.debug("Token Staked Successfully. MINE ID: " + + mineID); + + stakedTokenChainArray.put(stakingSigns); + writeToFile(TOKENCHAIN_PATH + stakedTokenHash + ".json", + stakedTokenChainArray.toString(), + false); + + + out.println(stakingSigns.toString()); + QuorumConsensusLogger.debug("Staking Completed!"); + + socket.close(); + serverSocket.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); + + } else { + QuorumConsensusLogger.debug("Token to stake not verified"); + out.println("447"); + socket.close(); + serverSocket.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); + } + } else { + QuorumConsensusLogger.debug("Token to stake not found"); + out.println("446"); socket.close(); serverSocket.close(); executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); } - QuorumConsensusLogger.debug("credit Signature " + creditSignatures); - - if (!creditSignatures.equals("null")) { // commented as per test for multiple consensus - // threads - - FileWriter shareWriter = new FileWriter(new File(LOGGER_PATH + "mycredit.txt"), true); - shareWriter.write(creditSignatures); - shareWriter.close(); - File readCredit = new File(LOGGER_PATH + "mycredit.txt"); - String credit = add(readCredit.toString(), ipfs); - - File creditFile = new File( - WALLET_DATA_PATH.concat("/Credits/").concat(credit).concat(".json")); - if (!creditFile.exists()) - creditFile.createNewFile(); - writeToFile(creditFile.toString(), creditSignatures, false); - - QuorumConsensusLogger.debug("Credit object: " + credit); - QuorumConsensusLogger.debug("Credit Hash: " + calculateHash(credit, "SHA3-256")); - JSONObject storeDetailsQuorum = new JSONObject(); - storeDetailsQuorum.put("tid", transactionID); - storeDetailsQuorum.put("consensusID", verifySenderHash); - storeDetailsQuorum.put("sign", senderPrivatePos); - storeDetailsQuorum.put("credits", credit); - storeDetailsQuorum.put("creditHash", calculateHash(credit, "SHA3-256")); - storeDetailsQuorum.put("senderdid", senderDidIpfsHash); - storeDetailsQuorum.put("Date", Functions.getCurrentUtcTime()); - storeDetailsQuorum.put("recdid", receiverDID); - JSONArray data = new JSONArray(); - data.put(storeDetailsQuorum); - QuorumConsensusLogger.debug("Quorum Share: " + credit); - updateJSON("add", WALLET_DATA_PATH + "QuorumSignedTransactions.json", data.toString()); - deleteFile(LOGGER_PATH + "mycredit.txt"); - writeToFile(LOGGER_PATH + "consenusIDhash", verifySenderHash, false); - String consenusIDhash = IPFSNetwork.add(LOGGER_PATH + "consenusIDhash", ipfs); - deleteFile(LOGGER_PATH + "consenusIDhash"); - QuorumConsensusLogger.debug("added consensus ID " + consenusIDhash); - } } else { - QuorumConsensusLogger.debug("Sender Authentication Failure - Quorum"); - out.println("Auth_Failed"); + QuorumConsensusLogger.debug("Token Staking Failed: Insufficient Balance to Stake!"); + out.println("445"); + socket.close(); + serverSocket.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); } - // ! moving staked token to bottom of BNK00 file. - + } else { + QuorumConsensusLogger.debug("Incorrect stake details"); + out.println("444"); + socket.close(); + serverSocket.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); } - } else { - QuorumConsensusLogger.debug("Quorum - " + didHash + " is unable to respond!" + getRecData); - out.println(getRecData); - } + } + else + QuorumConsensusLogger.debug("Old Credits Mining / Whole RBT Token Transfer"); + String getRecData = null; + try { + getRecData = in.readLine(); + + if (getRecData != null) { + if (getRecData.contains("ping check")) { + QuorumConsensusLogger.debug("Ping check from sender: " + getRecData); + out.println("pong response"); + } else { + + QuorumConsensusLogger.debug("Received Details from initiator: " + getRecData); + readSenderData = new JSONObject(getRecData); + senderPrivatePos = readSenderData.getString("sign"); + senderDidIpfsHash = readSenderData.getString("senderDID"); + transactionID = readSenderData.getString("Tid"); + verifySenderHash = readSenderData.getString("Hash"); + receiverDID = readSenderData.getString("RID"); + // initHash = readSenderData.getString(INIT_HASH); + + syncDataTable(senderDidIpfsHash, null); + + senderPID = getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", senderDidIpfsHash); + String senderWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "didHash", + senderDidIpfsHash); + + nodeData(senderDidIpfsHash, senderWidIpfsHash, ipfs); + String quorumHash = calculateHash(verifySenderHash.concat(receiverDID), "SHA3-256"); + + QuorumConsensusLogger.debug("1: " + senderPrivatePos); + QuorumConsensusLogger.debug("2: " + senderDidIpfsHash); + QuorumConsensusLogger.debug("3: " + transactionID); + QuorumConsensusLogger.debug("4: " + verifySenderHash); + + JSONObject detailsToVerify = new JSONObject(); + detailsToVerify.put("did", senderDidIpfsHash); + detailsToVerify.put("hash", verifySenderHash); + detailsToVerify.put("signature", senderPrivatePos); + + writeToFile(LOGGER_PATH + "tempverifysenderhash", verifySenderHash, false); + String verifySenderIPFSHash = IPFSNetwork.addHashOnly(LOGGER_PATH + "tempverifysenderhash", + ipfs); + deleteFile(LOGGER_PATH + "tempverifysenderhash"); + + if (Authenticate.verifySignature(detailsToVerify.toString())) { + QuorumConsensusLogger.debug("Quorum Authenticated Sender"); + + QuorumConsensusLogger.debug("ConsensusID pass"); + String QuorumSignature = getSignFromShares(DATA_PATH + didHash + "/PrivateShare.png", + quorumHash); + + QuorumConsensusLogger.debug(QuorumSignature); + out.println(QuorumSignature); + + String creditSignatures = null; + try { + creditSignatures = in.readLine(); + } catch (SocketException e) { + QuorumConsensusLogger.debug("Sender Input Stream Null - Credits"); + socket.close(); + serverSocket.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); + } + QuorumConsensusLogger.debug("credit Signature " + creditSignatures); + + if (!creditSignatures.equals("null")) { // commented as per test for multiple consensus + // threads + FileWriter shareWriter = new FileWriter(new File(LOGGER_PATH + "mycredit.txt"), true); + shareWriter.write(creditSignatures); + shareWriter.close(); + File readCredit = new File(LOGGER_PATH + "mycredit.txt"); + String credit = add(readCredit.toString(), ipfs); + + File creditFile = new File( + WALLET_DATA_PATH.concat("/Credits/").concat(credit).concat(".json")); + if (!creditFile.exists()) + creditFile.createNewFile(); + writeToFile(creditFile.toString(), creditSignatures, false); + + QuorumConsensusLogger.debug("Credit object: " + credit); + QuorumConsensusLogger.debug("Credit Hash: " + calculateHash(credit, "SHA3-256")); + JSONObject storeDetailsQuorum = new JSONObject(); + storeDetailsQuorum.put("tid", transactionID); + storeDetailsQuorum.put("consensusID", verifySenderHash); + storeDetailsQuorum.put("sign", senderPrivatePos); + storeDetailsQuorum.put("credits", credit); + storeDetailsQuorum.put("creditHash", calculateHash(credit, "SHA3-256")); + storeDetailsQuorum.put("senderdid", senderDidIpfsHash); + storeDetailsQuorum.put("Date", Functions.getCurrentUtcTime()); + storeDetailsQuorum.put("recdid", receiverDID); + JSONArray data = new JSONArray(); + data.put(storeDetailsQuorum); + QuorumConsensusLogger.debug("Quorum Share: " + credit); + updateJSON("add", WALLET_DATA_PATH + "QuorumSignedTransactions.json", data.toString()); + deleteFile(LOGGER_PATH + "mycredit.txt"); + writeToFile(LOGGER_PATH + "consenusIDhash", verifySenderHash, false); + String consenusIDhash = IPFSNetwork.add(LOGGER_PATH + "consenusIDhash", ipfs); + deleteFile(LOGGER_PATH + "consenusIDhash"); + QuorumConsensusLogger.debug("added consensus ID " + consenusIDhash); + } + + } else { + QuorumConsensusLogger.debug("Sender Authentication Failure - Quorum"); + out.println("Auth_Failed"); + } + + } + } else { + QuorumConsensusLogger.debug("Quorum - " + didHash + " is unable to respond!" + getRecData); + out.println(getRecData); + } + } catch (SocketException e) { + QuorumConsensusLogger.debug("Sender Input Stream Null - Ping Check / Receiver Details"); + socket.close(); + serverSocket.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPID); + } + } catch (IOException e) { QuorumConsensusLogger.error("IOException Occurred", e); } catch (JSONException e) { diff --git a/src/com/rubix/Consensus/StakeConsensus.java b/src/com/rubix/Consensus/StakeConsensus.java new file mode 100644 index 00000000..9858464f --- /dev/null +++ b/src/com/rubix/Consensus/StakeConsensus.java @@ -0,0 +1,341 @@ +package com.rubix.Consensus; + +import static com.rubix.Constants.MiningConstants.MINE_ID; +import static com.rubix.Constants.MiningConstants.MINE_ID_SIGN; +import static com.rubix.Constants.MiningConstants.STAKED_QUORUM_DID; +import static com.rubix.Resources.Functions.DATA_PATH; +import static com.rubix.Resources.Functions.LOGGER_PATH; +import static com.rubix.Resources.Functions.calculateHash; +import static com.rubix.Resources.Functions.getValues; +import static com.rubix.Resources.Functions.nodeData; +import static com.rubix.Resources.Functions.syncDataTable; +import static com.rubix.Resources.IPFSNetwork.forward; +import static com.rubix.Resources.IPFSNetwork.swarmConnectP2P; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.Socket; +import java.net.SocketException; +import java.util.ArrayList; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.json.JSONArray; +import org.json.JSONObject; + +import com.rubix.AuthenticateNode.Authenticate; +import com.rubix.Resources.IPFSNetwork; + +import io.ipfs.api.IPFS; + +public class StakeConsensus { + public static Logger StakeConsensusLogger = Logger.getLogger(StakeConsensus.class); + private static int socketTimeOut = 0; + public static volatile int STAKE_LOCKED = 0; + public static volatile int STAKE_SUCCESS = 0; + public static volatile int STAKE_FAILED = 0; + public static volatile JSONArray stakeDetails = new JSONArray(); + public static volatile ArrayList stakedDIDs = new ArrayList(); + // MINE_ID + // QST_HEIGHT + // STAKED_QUORUM_DID + // STAKED_TOKEN + // STAKED_TOKEN_SIGN + // MINE_ID_SIGN + // MINING_TID_SIGN + // MINED_RBT_SIGN + // same object will be added to tokenchains of staked and mined token + + public static void getStakeConsensus(JSONArray signedAphaQuorumArray, JSONObject data, IPFS ipfs, int PORT, + String operation) { + + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + String[] qResponse = new String[signedAphaQuorumArray.length()]; + Socket[] qSocket = new Socket[signedAphaQuorumArray.length()]; + PrintStream[] qOut = new PrintStream[signedAphaQuorumArray.length()]; + BufferedReader[] qIn = new BufferedReader[signedAphaQuorumArray.length()]; + String[] quorumPID = new String[signedAphaQuorumArray.length()]; + + StakeConsensusLogger.debug("Initiating Staking with " + signedAphaQuorumArray.length() + " Alpha Quorums: " + + signedAphaQuorumArray.toString()); + + try { + + for (int j = 0; j < signedAphaQuorumArray.length(); j++) + quorumPID[j] = signedAphaQuorumArray.getString(j); + + Thread[] quorumThreads = new Thread[signedAphaQuorumArray.length()]; + for (int i = 0; i < signedAphaQuorumArray.length(); i++) { + int j = i; + quorumThreads[i] = new Thread(() -> { + try { + StakeConsensusLogger.debug("Connecting to Quorum: " + quorumPID[j]); + + swarmConnectP2P(quorumPID[j], ipfs); + syncDataTable(null, quorumPID[j]); + String quorumDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", + quorumPID[j]); + String quorumWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "peerid", + quorumPID[j]); + nodeData(quorumDidIpfsHash, quorumWidIpfsHash, ipfs); + String appName = quorumPID[j].concat("alpha"); + StakeConsensusLogger.debug("quourm ID " + quorumPID[j] + " appname " + appName); + forward(appName, PORT + j, quorumPID[j]); + StakeConsensusLogger.debug( + "Connected to " + quorumPID[j] + " on port " + (PORT + j) + "with AppName" + appName); + qSocket[j] = new Socket("127.0.0.1", PORT + j); + qSocket[j].setSoTimeout(socketTimeOut); + qIn[j] = new BufferedReader(new InputStreamReader(qSocket[j].getInputStream())); + qOut[j] = new PrintStream(qSocket[j].getOutputStream()); + + qOut[j].println(operation); + if (operation.equals("alpha-stake-token")) { + + qOut[j].println(data.toString()); + + String stakerDID = getValues(DATA_PATH + "DataTable.json", "didHash", + "peerid", + quorumPID[j]); + StakeConsensusLogger.debug("stakerDID is " + stakerDID); + StakeConsensusLogger.debug("Mined Token Details sent for validation...Staker DID is : " + stakerDID); + + + try { + qResponse[j] = qIn[j].readLine(); + + if (qResponse[j] != null && qResponse[j].equals("tokenToStake")) { + + try { + qResponse[j] = qIn[j].readLine(); + + if (qResponse[j] != null) { + /****** start */ + + StakeConsensusLogger + .debug("Mined Token Details validated. Received staked token details from DID: " + + stakerDID); + Boolean ownerCheck = true; + + JSONArray stakeTokenArray = new JSONArray(qResponse[j]); + String stakeTokenHash = stakeTokenArray.getString(0); + JSONArray stakeTC = stakeTokenArray.getJSONArray(1); + String positionsArray = stakeTokenArray.getString(2); + + // ! check ownership of stakeTC from Token Receiver logic + + if (stakeTC.length() > 0 && stakeTokenHash != null + && positionsArray != null) { + + JSONObject lastObject = stakeTC.getJSONObject(stakeTC.length() - 1); + StakeConsensusLogger.debug("Last Object = " + lastObject); + if (lastObject.has("owner")) { + StakeConsensusLogger + .debug("Checking ownership of " + stakeTokenHash + + " from DID " + + lastObject.getString("owner") + + " for positions send: " + + positionsArray); + String owner = lastObject.getString("owner"); + String tokens = stakeTokenHash; + String hashString = tokens.concat(stakerDID); + String hashForPositions = calculateHash(hashString, "SHA3-256"); + String ownerIdentity = hashForPositions.concat(positionsArray); + String ownerRecalculated = calculateHash(ownerIdentity, "SHA3-256"); + + StakeConsensusLogger.debug("Ownership Here Sender Calculation"); + StakeConsensusLogger.debug("tokens: " + tokens); + StakeConsensusLogger.debug("hashString: " + hashString); + StakeConsensusLogger.debug("hashForPositions: " + hashForPositions); + StakeConsensusLogger.debug("p1: " + positionsArray); + StakeConsensusLogger.debug("ownerIdentity: " + ownerIdentity); + StakeConsensusLogger + .debug("ownerIdentityHash: " + ownerRecalculated); + + if (!owner.equals(ownerRecalculated)) { + ownerCheck = false; + // STAKE_FAILED++; + StakeConsensusLogger.debug( + "Ownership Check Failed for index " + j + " with DID: " + + owner); + IPFSNetwork.executeIPFSCommands( + "ipfs p2p close -t /p2p/" + quorumPID[j]); + } + + } + } else { + ownerCheck = false; + // STAKE_FAILED++; + StakeConsensusLogger + .debug("insufficient stake token height details from DID: " + + stakerDID); + IPFSNetwork + .executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumPID[j]); + } + + if (ownerCheck && !(STAKE_LOCKED > 2)) { + StakeConsensusLogger + .debug("Ownership Check Success for Peer: " + quorumPID[j]); + STAKE_LOCKED++; + qOut[j].println("alpha-stake-token-verified"); + StakeConsensusLogger + .debug("Staking locked with for Peer: " + quorumPID[j]); + StakeConsensusLogger.debug("Waiting for stake signatures"); + + try { + qResponse[j] = qIn[j].readLine(); + StakeConsensusLogger + .debug("Received stake token signatures: " + qResponse[j]); + + if (qResponse[j] != null && qResponse[j].equals("447")) { + STAKE_FAILED++; + StakeConsensusLogger.debug("Token to stake not verified"); + IPFSNetwork.executeIPFSCommands( + "ipfs p2p close -t /p2p/" + quorumPID[j]); + } else if (qResponse[j] != null) { + // ! add mine signs to tokenchain + StakeConsensusLogger.debug("Adding mine signatures"); + JSONObject mineSigns = new JSONObject(qResponse[j]); + StakeConsensusLogger.debug("mineSign is "+mineSigns.toString()); + + if (mineSigns.length() > 0) { + + // stakeDetails = mineSigns; + + String quorumDID = getValues(DATA_PATH + "DataTable.json", + "didHash", "peerid", + quorumPID[j]); + + // ! validate signatures + StakeConsensusLogger + .debug("Validating Signatures from DID: " + + stakerDID); + JSONObject mineIDSign = new JSONObject(); + mineIDSign.put("did", quorumDID); + mineIDSign.put("hash", mineSigns.getString(MINE_ID)); + mineIDSign.put("signature", + mineSigns.getString(MINE_ID_SIGN)); + + ArrayList ownersArray = new ArrayList(); + ownersArray = IPFSNetwork.dhtOwnerCheck(MINE_ID); + + if (ownersArray.contains(STAKED_QUORUM_DID)) { + StakeConsensusLogger + .debug("Staking pin check passed: " + mineSigns + .getString(STAKED_QUORUM_DID)); + } else { + IPFSNetwork.executeIPFSCommands( + "ipfs p2p close -t /p2p/" + quorumPID[j]); + StakeConsensusLogger.debug( + "Staking pin check failed for DID: " + mineSigns + .getString(STAKED_QUORUM_DID)); + } + + boolean mineSignCheck = Authenticate + .verifySignature(mineIDSign.toString()); + + if (mineSignCheck) { + StakeConsensusLogger.debug( + "########--Staking Complete " + STAKE_SUCCESS + + "/5 !--########"); + + // qOut[j].println("200"); + StakeConsensusLogger.debug( + "Staking completed for Peer: " + quorumPID[j]); + stakedDIDs.add(quorumDID); + stakeDetails.put(mineSigns); + STAKE_SUCCESS++; + }else { + STAKE_FAILED++; + } + } else { + STAKE_FAILED++; + StakeConsensusLogger.debug( + "Stake signatures not received from DID: " + + stakerDID + " Quorum response: " + + qResponse[j]); + IPFSNetwork.executeIPFSCommands( + "ipfs p2p close -t /p2p/" + quorumPID[j]); + } + } + + } catch (SocketException e) { + STAKE_FAILED++; + StakeConsensusLogger + .debug("Mined Token Details validation failed for DID: " + + stakerDID + " Received null response"); + } + + } else { + STAKE_FAILED++; + StakeConsensusLogger.debug("Ownership Check Failed"); + IPFSNetwork + .executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumPID[j]); + } + + /** End */ + } + + } catch (SocketException e) { + STAKE_FAILED++; + StakeConsensusLogger + .debug("Mined Token Details validation failed. Received null response"); + IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumPID[j]); + } + + } else if (qResponse[j] != null && qResponse[j].equals("446")) { + STAKE_FAILED++; + StakeConsensusLogger + .debug("No token is available to stake is corroupted. Skipping...DID: " + + stakerDID); + IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumPID[j]); + } else if (qResponse[j].equals("445")) { + STAKE_FAILED++; + StakeConsensusLogger.debug("Insufficient quorum member balance. Skipping...DID: " + + stakerDID); + IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumPID[j]); + } else if (qResponse[j].equals("444")) { + STAKE_FAILED++; + StakeConsensusLogger.debug("Quorum could not verify mined token. Skipping...DID: " + + stakerDID); + IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumPID[j]); + } else { + STAKE_FAILED++; + StakeConsensusLogger.debug("Unexpected response from staker: " + qResponse[j]); + IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumPID[j]); + } + + } catch (SocketException e) { + STAKE_FAILED++; + StakeConsensusLogger + .debug("Mined Token Details validation failed for DID: " + stakerDID + + " Received null response"); + IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + quorumPID[j]); + } + + } + + } catch (Exception e) { + STAKE_FAILED++; + StakeConsensusLogger.error("Error in quorum consensus thread: " + e); + } + StakeConsensusLogger.debug("*******STAKE_SUCCESS********* " + STAKE_SUCCESS + + " **********STAKE_FAILED*********** " + STAKE_FAILED); + }); + quorumThreads[j].start(); + + // do { + // } while (STAKE_SUCCESS < 2 || STAKE_FAILED < 3); + + } + + do { + } while (STAKE_SUCCESS < 3 && STAKE_FAILED < 3); + + } catch (Exception e) { + StakeConsensusLogger.error("Error in getStakeConsensus: " + e); + } + + } + +} diff --git a/src/com/rubix/Constants/ConsensusConstants.java b/src/com/rubix/Constants/ConsensusConstants.java index b67e588c..1a76e6f8 100644 --- a/src/com/rubix/Constants/ConsensusConstants.java +++ b/src/com/rubix/Constants/ConsensusConstants.java @@ -1,11 +1,11 @@ package com.rubix.Constants; - public class ConsensusConstants { public static final String TRANSACTION_ID = "Tid"; public static final String HASH = "Hash"; public static final String RECEIVERID = "RID"; - + public static final String INIT_HASH = "initHash"; + public static final String MINE_XORER = "yhevnyxcwblibeikfagmazsldzkfgnqwmketmcubnuvlbb"; } diff --git a/src/com/rubix/Constants/MiningConstants.java b/src/com/rubix/Constants/MiningConstants.java new file mode 100644 index 00000000..4d44faed --- /dev/null +++ b/src/com/rubix/Constants/MiningConstants.java @@ -0,0 +1,17 @@ +package com.rubix.Constants; + +public class MiningConstants { + + public static final String MINE_TID = "mineTransactionID"; + public static final String MINED_RBT = "minedToken"; + public static final String MINE_ID = "mineID"; + public static final String STAKED_QUORUM_DID = "stakedQuorumDID"; + public static final String STAKE_DATA = "stakeData"; + public static final String STAKED_TOKEN = "stakedToken"; + public static final String STAKED_TOKEN_SIGN = "stakedTokenSignature"; + public static final String MINING_TID_SIGN = "TIDSignature"; + public static final String MINED_RBT_SIGN = "minedTokenSignature"; + public static final String MINE_ID_SIGN = "mineIDSignature"; + public static final String QST_HEIGHT = "QSTHeight"; + public static final String QUORUM_SIGN_CONTENT = "quorumSignContent"; +} \ No newline at end of file diff --git a/src/com/rubix/Mining/HashChain.java b/src/com/rubix/Mining/HashChain.java new file mode 100644 index 00000000..3039ef6b --- /dev/null +++ b/src/com/rubix/Mining/HashChain.java @@ -0,0 +1,145 @@ +package com.rubix.Mining; + +import com.rubix.Resources.Functions; + +import java.util.ArrayList; +import java.util.Random; + +import org.apache.log4j.Logger; + +public class HashChain { + static String hashChain = ""; + + public static Logger HashChainLogger = Logger.getLogger(HashChain.class); + + public static String newHashChain(String tID, String[] DIDs, int rule) { + long totalTime = 0; + long currentTime = 0; + int ctr = 0; + java.util.Date date = new java.util.Date(); + while(totalTime<3600000 || rule > tID.length()) { + + // currentTime = hashChainCounter(tID, DIDs,rule+ctr); + totalTime = totalTime + currentTime; + //System.out.println("Counter is "+ctr+" Current time used is "+ totalTime); + ctr++; + currentTime = 0; + + + } + return hashChain; + + } + + + public static String hashChainCounter(String tID, ArrayList DIDs, int rule) { + //String hashChain = ""; + long start = 0; + long end = 0; + start = System.currentTimeMillis(); + Random rand = new Random(); + String DID = DIDs.get(rand.nextInt(3)) ; + //DIDs[rand.nextInt(3)]; + //for (String DID : DIDs) { + int counter = 0; + String hash = DID; + while (!hash.endsWith(tID.substring(tID.length() - rule))) { + counter++; + hash = Functions.calculateHash(hash, "SHA3-256"); + hashChain = hash; + } + + // System.out.println(hash + " " + counter + " rule is "+ rule); + // } + end = System.currentTimeMillis(); + // System.out.println("Current time "+(end - start)); + return hashChain; + } + + // using the TID and DIDs, + + // fetch TID and DIDs as inputs. TID will hash itself until the last 3 char of + // TID matches with any of the DIDs in the list. + + // public static String getTID(String TID, String DIDs) { + + // token is the TID that + + // public static String newHashChain(String TID, String[] DIDs) { + // String TIDHash = TID; + + // while (!(TIDHash.substring(TIDHash.length() - 5), DIDs)) { + // TIDHash = Functions.calculateHash(TIDHash, "SHA3-256"); + // } + + // return TIDHash; + // } + + // write a function which takes a string as TID and string array as DIDs. TID + // will hash itself until last 5 characters are same as any one of the DIDs. + // If not found, return null. + + // write a function which takes a string as TID and string array as DIDs. The + // function should return the average iterations each DID took to rehash itself + // to match the last 3 char of TID + // public static String newHashChain(String TID, String[] DIDs, int matchRule) { + // int[] averageIterations = new int[DIDs.length]; + // for (int i = 0; i < DIDs.length; i++) { + // averageIterations[i] = averageIterations(TID, DIDs[i], matchRule); + // } + // // get the average of values in the array + // int sum = 0; + // for (int i = 0; i < averageIterations.length; i++) { + // System.out.println("averageIterations[" + i + "] = " + averageIterations[i]); + // sum += averageIterations[i]; + // } + // int average = sum / averageIterations.length; + // return Integer.toString(average); + // } + + // private static int averageIterations(String TID, String DID, int matchRule) { + // int iterations = 0; + // String last3Chars = TID.substring(TID.length() - matchRule); + // String currentDID = DID; + // while (!currentDID.substring(currentDID.length() - + // matchRule).equals(last3Chars)) { + // currentDID = Functions.calculateHash(currentDID, "SHA3-256"); + // iterations++; + + // } + // System.out.println(currentDID + " " + iterations); + + // return iterations; + // } + + // public static String newHashChain(String TID, String[] DIDs) { + // String TIDHash = TID; + + // while (!Functions.isSame(TIDHash.substring(TIDHash.length() - 5), DIDs)) { + // TIDHash = Functions.calculateHash(TIDHash, "SHA3-256"); + // } + + // return TIDHash; + // } + + // public static String newHashChain(String tID, String[] DIDs, int matchRule) { + // String hashChain = ""; + // int counter = 0; + // for (String DID : DIDs) { + + // String hash = DID; + // while (!hash.endsWith(tID.substring(tID.length() - DIDs.length))) { + // // hashChain += hash; + // counter++; + // hash = Functions.calculateHash(hash, "SHA3-256"); + // hashChain = hash; + // System.out.println(hash + " " + counter); + // } + + // } + + // return hashChain; + + // } + +} diff --git a/src/com/rubix/Mining/ProofCredits.java b/src/com/rubix/Mining/ProofCredits.java index e4ce6292..b42118be 100644 --- a/src/com/rubix/Mining/ProofCredits.java +++ b/src/com/rubix/Mining/ProofCredits.java @@ -14,10 +14,13 @@ import static com.rubix.Resources.Functions.calculateHash; import static com.rubix.Resources.Functions.deleteFile; import static com.rubix.Resources.Functions.getQuorum; -import static com.rubix.Resources.Functions.initHash; +import static com.rubix.Resources.Functions.getValues; import static com.rubix.Resources.Functions.minQuorum; import static com.rubix.Resources.Functions.mineUpdate; import static com.rubix.Resources.Functions.readFile; +import static com.rubix.Resources.Functions.sanityCheck; +import static com.rubix.Resources.Functions.sanityMessage; +import static com.rubix.Resources.Functions.strToIntArray; import static com.rubix.Resources.Functions.updateJSON; import static com.rubix.Resources.Functions.updateQuorum; import static com.rubix.Resources.Functions.writeToFile; @@ -25,9 +28,11 @@ import static com.rubix.Resources.IPFSNetwork.pin; import static com.rubix.Resources.IPFSNetwork.repo; +import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; @@ -40,10 +45,14 @@ import java.util.Iterator; import java.util.List; +import javax.imageio.ImageIO; import javax.net.ssl.HttpsURLConnection; +import com.rubix.AuthenticateNode.PropImage; import com.rubix.Consensus.InitiatorConsensus; import com.rubix.Consensus.InitiatorProcedure; +import com.rubix.Consensus.StakeConsensus; +import com.rubix.Constants.MiningConstants; import com.rubix.Resources.Functions; import com.rubix.Resources.IPFSNetwork; @@ -61,21 +70,37 @@ public class ProofCredits { private static ArrayList betaPeersList; private static ArrayList gammaPeersList; private static int alphaSize = 0; + public static String hashChainProof = new String(); + private static int hashChainRule = 7; + public static JSONObject create(String data, IPFS ipfs) throws IOException, JSONException { + StakeConsensus.STAKE_SUCCESS = 0; + StakeConsensus.STAKE_LOCKED = 0; + StakeConsensus.STAKE_FAILED = 0; + StakeConsensus.stakeDetails = new JSONArray(); + InitiatorConsensus.signedAphaQuorumArray = new JSONArray(); + InitiatorConsensus.quorumWithShares = new ArrayList<>(); + InitiatorConsensus.finalQuorumSignsArray = new JSONArray(); + InitiatorConsensus.quorumSignature = new JSONObject(); repo(ipfs); JSONObject APIResponse = new JSONObject(); JSONObject detailsObject = new JSONObject(data); - String receiverDidIpfsHash = detailsObject.getString("receiverDidIpfsHash"); + String DID = detailsObject.getString("receiverDidIpfsHash"); String pvt = detailsObject.getString("pvt"); int type = detailsObject.getInt("type"); int creditUsed = 0; long totalTime = 0; + int QSTHeight = 0; JSONArray alphaQuorum = new JSONArray(); JSONArray betaQuorum = new JSONArray(); JSONArray gammaQuorum = new JSONArray(); + JSONArray qstArray = new JSONArray(); + + boolean Status = false; + int creditsRequired = 50000, level; long starttime = System.currentTimeMillis(); @@ -86,8 +111,19 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON JSONArray newQstArray = new JSONArray(readFile(WALLET_DATA_PATH + "QuorumSignedTransactions.json")); int availableCredits = newQstArray.length(); + File minedCH = new File(WALLET_DATA_PATH + "MinedCreditsHistory.json"); + if (!minedCH.exists()) { + minedCH.createNewFile(); + writeToFile(WALLET_DATA_PATH + "MinedCreditsHistory.json", "[]", false); + } + String creditsHistory = readFile(WALLET_DATA_PATH + "MinedCreditsHistory.json"); + JSONArray creditsHistoryArray = new JSONArray(creditsHistory); + + // ! get actual qst height for current scenario + QSTHeight = availableCredits + creditsHistoryArray.length(); + ProofCreditsLogger.debug("Credits available: " + availableCredits); - String GET_URL_credit = SYNC_IP + "/getlevel"; + String GET_URL_credit = SYNC_IP + "/getCurrentLevel"; URL URLobj_credit = new URL(GET_URL_credit); HttpURLConnection con_credit = (HttpURLConnection) URLobj_credit.openConnection(); con_credit.setRequestMethod("GET"); @@ -101,7 +137,8 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON response_credit.append(inputLine_credit); } in_credit.close(); - ProofCreditsLogger.debug("response from service " + response_credit.toString()); + // ProofCreditsLogger.debug("response from service " + + // response_credit.toString()); resJsonData_credit = new JSONObject(response_credit.toString()); int level_credit = resJsonData_credit.getInt("level"); creditsRequired = (int) Math.pow(2, (2 + level_credit)); @@ -121,8 +158,27 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON ProofCreditsLogger.debug("Credits Old: " + oldCreditsFlag); + JSONArray quorumArray; + switch (type) { + case 2: { + quorumArray = new JSONArray(readFile(DATA_PATH + "quorumlist.json")); + break; + } + default: { + quorumArray = getQuorum(DID, DID, 1); + if (quorumArray.length() == 1) { + APIResponse.put("did", DID); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Type 1 mining not allowed. Please use subnet quorum to mine."); + ProofCreditsLogger.warn("Quorum Members not available for type 1 mining"); + return APIResponse; + } + } + } + // String GET_URL = SYNC_IP+"/getInfo?count="+availableCredits; - String GET_URL = SYNC_IP + "/minetoken"; + String GET_URL = SYNC_IP + "/getTokenToMine"; URL URLobj = new URL(GET_URL); HttpURLConnection con = (HttpURLConnection) URLobj.openConnection(); con.setRequestMethod("GET"); @@ -136,7 +192,7 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON response.append(inputLine); } in.close(); - ProofCreditsLogger.debug("response from service " + response.toString()); + // ProofCreditsLogger.debug("response from service " + response.toString()); resJsonData = new JSONArray(response.toString()); } else @@ -150,6 +206,11 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON level = resJsonData.getJSONObject(0).getInt("level"); for (int i = 0; i < resJsonData.length(); i++) { + ProofCreditsLogger + .debug("*************level**********" + resJsonData.getJSONObject(i).getInt("level")); + ProofCreditsLogger + .debug("*************token**********" + resJsonData.getJSONObject(i).getInt("token")); + token.put(Functions.mineToken(resJsonData.getJSONObject(i).getInt("level"), resJsonData.getJSONObject(i).getInt("token"))); @@ -163,29 +224,66 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON JSONArray prooftid = new JSONArray(); String comments = resJsonData.toString() + prooftid; - String authSenderByRecHash = calculateHash(token + receiverDidIpfsHash + comments, "SHA3-256"); + String authSenderByRecHash = calculateHash(token + DID + comments, "SHA3-256"); String tid = calculateHash(authSenderByRecHash, "SHA3-256"); - writeToFile(LOGGER_PATH + "tempbeta", tid.concat(receiverDidIpfsHash), false); - String betaHash = IPFSNetwork.add(LOGGER_PATH + "tempbeta", ipfs); - deleteFile(LOGGER_PATH + "tempbeta"); - - writeToFile(LOGGER_PATH + "tempgamma", tid.concat(receiverDidIpfsHash), false); - String gammaHash = IPFSNetwork.add(LOGGER_PATH + "tempgamma", ipfs); - deleteFile(LOGGER_PATH + "tempgamma"); - - JSONArray quorumArray; - switch (type) { - case 2: { - quorumArray = new JSONArray(readFile(DATA_PATH + "quorumlist.json")); - break; - } - default: { - quorumArray = getQuorum(betaHash, gammaHash, receiverDidIpfsHash, receiverDidIpfsHash, - token.length()); + // writeToFile(LOGGER_PATH + "tempbeta", tid.concat(DID), false); + // String betaHash = IPFSNetwork.add(LOGGER_PATH + "tempbeta", ipfs); + // deleteFile(LOGGER_PATH + "tempbeta"); + + // writeToFile(LOGGER_PATH + "tempgamma", tid.concat(DID), false); + // String gammaHash = IPFSNetwork.add(LOGGER_PATH + "tempgamma", ipfs); + // deleteFile(LOGGER_PATH + "tempgamma"); + + + + ProofCreditsLogger.debug("DID is "+DID); + ProofCreditsLogger.debug("Quorums list is "+quorumArray.toString()); + if(quorumArray.toString().contains(DID)) { + JSONArray updatedQuourmList = new JSONArray(); + ProofCreditsLogger.debug("Miner DID "+ DID + "is found in quourmArray"); + for(int i=0;i= 7 && i <= 13) + betaCheck++; + if (i >= 14 && i <= 20) + gammaCheck++; } } + if (alphaCheck > 2 || betaCheck > 2 || gammaCheck > 2) { + APIResponse.put("did", DID); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + String message = "Quorum: ".concat(sanityFailedQuorum.toString()).concat(" "); + APIResponse.put("message", message.concat(sanityMessage)); + ProofCreditsLogger.warn("Quorum: ".concat(message.concat(sanityMessage))); + return APIResponse; + } + //Sanity Check - Ends + QuorumSwarmConnect(quorumArray, ipfs); alphaSize = quorumArray.length() - 14; @@ -211,7 +309,7 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON if (alphaPeersList.size() < minQuorum(alphaSize) || betaPeersList.size() < 5 || gammaPeersList.size() < 5) { updateQuorum(quorumArray, null, false, type); - APIResponse.put("did", receiverDidIpfsHash); + APIResponse.put("did", DID); APIResponse.put("tid", "null"); APIResponse.put("status", "Failed"); APIResponse.put("message", "Quorum Members not available"); @@ -220,11 +318,12 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON } JSONArray signedQuorumList = new JSONArray(); - if (!oldCreditsFlag) { + boolean creditRemoveStatus = false; + if (!oldCreditsFlag) { ProofCreditsLogger.debug("New Credits"); // Send QST for verification String qstContent = readFile(WALLET_DATA_PATH.concat("QuorumSignedTransactions.json")); - JSONArray qstArray = new JSONArray(qstContent); + qstArray = new JSONArray(qstContent); int count = 0; JSONArray creditSignsArray = new JSONArray(); @@ -254,7 +353,7 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON qstObject.put("credits", creditSignsArray); } else { updateQuorum(quorumArray, null, false, type); - APIResponse.put("did", receiverDidIpfsHash); + APIResponse.put("did", DID); APIResponse.put("tid", "null"); APIResponse.put("status", "Failed"); APIResponse.put("message", "Credit File(s) missing"); @@ -265,25 +364,25 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON JSONObject dataObject = new JSONObject(); dataObject.put("tid", tid); dataObject.put("message", comments); - dataObject.put("receiverDidIpfs", receiverDidIpfsHash); + dataObject.put("receiverDidIpfs", DID); dataObject.put("pvt", pvt); - dataObject.put("senderDidIpfs", receiverDidIpfsHash); + dataObject.put("senderDidIpfs", DID); dataObject.put("token", token.toString()); dataObject.put("alphaList", alphaPeersList); dataObject.put("betaList", betaPeersList); dataObject.put("gammaList", gammaPeersList); - dataObject.put("initHash", initHash()); dataObject.put("qstDetails", qstObject); InitiatorProcedure.consensusSetUp(dataObject.toString(), ipfs, SEND_PORT + 3, alphaSize, "new-credits-mining"); if (!(InitiatorConsensus.quorumSignature.length() >= 3 * minQuorum(7))) { - APIResponse.put("did", receiverDidIpfsHash); + APIResponse.put("did", DID); APIResponse.put("tid", "null"); APIResponse.put("status", "Failed"); APIResponse.put("message", "Consensus failed"); ProofCreditsLogger.debug("consensus failed"); + return APIResponse; } else { ProofCreditsLogger.debug("token mined " + token); @@ -297,9 +396,7 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON } } - for (int i = 0; i < creditUsed; i++) - deleteFile(WALLET_DATA_PATH.concat("/Credits/") - .concat(qstArray.getJSONObject(i).getString("credits")).concat(".json")); + creditRemoveStatus = true; } } else { @@ -308,9 +405,9 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON JSONObject dataObject = new JSONObject(); dataObject.put("tid", tid); dataObject.put("message", comments); - dataObject.put("receiverDidIpfs", receiverDidIpfsHash); + dataObject.put("receiverDidIpfs", DID); dataObject.put("pvt", pvt); - dataObject.put("senderDidIpfs", receiverDidIpfsHash); + dataObject.put("senderDidIpfs", DID); dataObject.put("token", token.toString()); dataObject.put("alphaList", alphaPeersList); dataObject.put("betaList", betaPeersList); @@ -319,7 +416,7 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON InitiatorProcedure.consensusSetUp(dataObject.toString(), ipfs, SEND_PORT + 3, alphaSize, ""); if (!(InitiatorConsensus.quorumSignature.length() >= 3 * minQuorum(7))) { - APIResponse.put("did", receiverDidIpfsHash); + APIResponse.put("did", DID); APIResponse.put("tid", "null"); APIResponse.put("status", "Failed"); APIResponse.put("message", "Consensus failed"); @@ -338,27 +435,150 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON } } } + // JSONObject stakingData = new JSONObject(); + // String tkHash = null; for (int i = 0; i < token.length(); i++) { + writeToFile(LOGGER_PATH + "tempToken", token.getString(i), false); String tokenHash = IPFSNetwork.add(LOGGER_PATH + "tempToken", ipfs); - writeToFile(TOKENS_PATH + tokenHash, token.getString(i), false); - deleteFile(LOGGER_PATH + "tempToken"); - writeToFile(TOKENCHAIN_PATH + tokenHash + ".json", "[]", false); - JSONObject temp = new JSONObject(); - temp.put("tokenHash", tokenHash); - JSONArray tempArray = new JSONArray(); - tempArray.put(temp); - updateJSON("add", PAYMENTS_PATH + "BNK00.json", tempArray.toString()); + + FileWriter shareWriter = new FileWriter(new File(LOGGER_PATH + "mycredit.txt"), true); + shareWriter.write(InitiatorConsensus.quorumSignature.toString()); + shareWriter.close(); + File readCredit = new File(LOGGER_PATH + "mycredit.txt"); + String credit = add(readCredit.toString(), ipfs); + + File creditFile = new File(WALLET_DATA_PATH.concat("/Credits/").concat(credit).concat(".json")); + if (!creditFile.exists()) + creditFile.createNewFile(); + writeToFile(creditFile.toString(), InitiatorConsensus.quorumSignature.toString(), false); + + String tokens = tokenHash; + String hashString = tokens.concat(DID); + String hashForPositions = calculateHash(hashString, "SHA3-256"); + + BufferedImage privateImage = ImageIO + .read(new File(DATA_PATH.concat(DID).concat("/PrivateShare.png"))); + String firstPrivate = PropImage.img2bin(privateImage); + int[] privateIntegerArray1 = strToIntArray(firstPrivate); + String privateBinary = Functions.intArrayToStr(privateIntegerArray1); + String positions = ""; + + for (int j = 0; j < privateIntegerArray1.length; j += 49152) { + positions += privateBinary.charAt(j); + } + String ownerIdentity = hashForPositions.concat(positions); + String ownerIdentityHash = calculateHash(ownerIdentity, "SHA3-256"); + + ProofCreditsLogger.debug("Ownership Here"); + ProofCreditsLogger.debug("tokens: " + tokenHash); + ProofCreditsLogger.debug("hashString: " + hashString); + ProofCreditsLogger.debug("hashForPositions: " + hashForPositions); + ProofCreditsLogger.debug("p1: " + positions); + ProofCreditsLogger.debug("QSTHeight: " + QSTHeight); + ProofCreditsLogger.debug("ownerIdentity: " + ownerIdentity); + ProofCreditsLogger.debug("ownerIdentityHash: " + ownerIdentityHash); + JSONArray tokenChainArray = new JSONArray(); + JSONObject tokenChainGenesisObject = new JSONObject(); + tokenChainGenesisObject.put("quorumSignatures", credit); + tokenChainGenesisObject.put("quorumSignContent", InitiatorConsensus.quorumSignature); + tokenChainGenesisObject.put("sender", DID); + tokenChainGenesisObject.put("comment", "Mining-Genesis"); + tokenChainGenesisObject.put("tid", tid); + tokenChainGenesisObject.put("owner", ownerIdentityHash); + tokenChainGenesisObject.put("blockNumber", 0); + tokenChainGenesisObject.put("QSTHeight", QSTHeight); + tokenChainGenesisObject.put("tokenHash", tokenHash); + tokenChainGenesisObject.put("tokenContent", token.getString(i)); + + tokenChainGenesisObject.put("nextHash", calculateHash(tid, "SHA3-256")); + tokenChainGenesisObject.put("previousHash", ""); + // stakingData = tokenChainGenesisObject; + // tkHash = tokenHash; + + //tokenChainArray.put(tokenChainGenesisObject); + // ! new token will now need a staked token + + /* + * do { } while (StakeConsensus.stakeDetails.length() < 8 || + * StakeConsensus.STAKE_FAILED == 5); + */ + + Thread stakingThread = new Thread(() -> { + try { + StakeConsensus.getStakeConsensus(InitiatorConsensus.signedAphaQuorumArray, + tokenChainGenesisObject, ipfs, SEND_PORT + 3, + "alpha-stake-token"); + } catch (Exception e) { + e.printStackTrace(); + } + }); + stakingThread.start(); + + while ((StakeConsensus.STAKE_SUCCESS < 3 && StakeConsensus.STAKE_FAILED < 3)) { + + } + ProofCreditsLogger.debug("Stake consensus stake details is "+ StakeConsensus.stakeDetails.toString()); + if (StakeConsensus.STAKE_SUCCESS == 3 && StakeConsensus.stakeDetails.length() > 0) { + tokenChainGenesisObject.put(MiningConstants.MINE_ID, StakeConsensus.stakeDetails); + tokenChainArray.put(tokenChainGenesisObject); + + ProofCreditsLogger.debug("Stake Details for new mined token: " + StakeConsensus.stakeDetails); + ProofCreditsLogger.debug("Staked quorums are "+ StakeConsensus.stakedDIDs); + ProofCreditsLogger.debug("-----------------------------------------------"); + ProofCreditsLogger.debug("Staked quorums are :"); + for (String ele : StakeConsensus.stakedDIDs) { + ProofCreditsLogger.debug(ele+" "); + } + ProofCreditsLogger.debug("-----------------------------------------------"); + writeToFile(TOKENS_PATH + tokenHash, token.getString(i), false); + ProofCreditsLogger.warn(" TOKENHASH " + tokenHash); + ProofCreditsLogger.warn(" TOKENS " + token.getString(i)); + deleteFile(LOGGER_PATH + "tempToken"); + writeToFile(TOKENCHAIN_PATH + tokenHash + ".json", tokenChainArray.toString(), false); + JSONObject temp = new JSONObject(); + temp.put("tokenHash", tokenHash); + JSONArray tempArray = new JSONArray(); + tempArray.put(temp); + hashChainProof = HashChain.hashChainCounter(tid, StakeConsensus.stakedDIDs, hashChainRule); + ProofCreditsLogger.debug("HashChainProof is "+hashChainProof+" transcation id is "+ tid); + updateJSON("add", PAYMENTS_PATH + "BNK00.json", tempArray.toString()); + } else { + updateQuorum(quorumArray, null, false, type); + APIResponse.put("did", DID); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Staking failed.. Retry with alpha quorum members with aleast 1 RBT balance"); + ProofCreditsLogger.warn("Staking failed"); + return APIResponse; + } + + } - File minedCH = new File(WALLET_DATA_PATH + "MinedCreditsHistory.json"); - if (!minedCH.exists()) { - minedCH.createNewFile(); - writeToFile(WALLET_DATA_PATH + "MinedCreditsHistory.json", "[]", false); + // updateJSON("add", TOKENCHAIN_PATH + tkHash + ".json", tempArray.toString()); + + if (!(InitiatorConsensus.quorumSignature.length() >= 3 * minQuorum(7))) { + APIResponse.put("did", DID); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Consensus failed"); + ProofCreditsLogger.debug("consensus failed"); + } else { + ProofCreditsLogger.debug("token mined " + token); + + int counter = 0; + + for (int i = 0; i < availableCredits; i++) { + JSONObject temp = newQstArray.getJSONObject(i); + if (counter < creditUsed) { + prooftid.put(temp.getString("tid")); + counter++; + } + } } - String creditsHistory = readFile(WALLET_DATA_PATH + "MinedCreditsHistory.json"); - JSONArray creditsHistoryArray = new JSONArray(creditsHistory); for (int i = 0; i < creditUsed; i++) { JSONObject minedObject = new JSONObject(); minedObject.put("tid", newQstArray.getJSONObject(i).getString("tid")); @@ -383,8 +603,8 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON signedQuorumList.put(keys.next()); updateQuorum(quorumArray, signedQuorumList, true, type); - mineUpdate(receiverDidIpfsHash, creditUsed); - APIResponse.put("did", receiverDidIpfsHash); + mineUpdate(DID, creditUsed); + APIResponse.put("did", DID); APIResponse.put("tid", tid); APIResponse.put("token", token); APIResponse.put("creditsused", creditUsed); @@ -401,11 +621,17 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON transactionRecord.put("tokens", token); transactionRecord.put("txn", tid); transactionRecord.put("quorumList", signedQuorumList); - transactionRecord.put("senderDID", receiverDidIpfsHash); - transactionRecord.put("receiverDID", receiverDidIpfsHash); + transactionRecord.put("senderDID", DID); + transactionRecord.put("receiverDID", DID); transactionRecord.put("Date", currentTime); transactionRecord.put("totalTime", totalTime); transactionRecord.put("comment", "minedtxn"); + + if(creditRemoveStatus == true) { + for (int i = 0; i < creditUsed; i++) + deleteFile(WALLET_DATA_PATH.concat("/Credits/") + .concat(qstArray.getJSONObject(i).getString("credits")).concat(".json")); + } JSONArray transactionHistoryEntry = new JSONArray(); transactionHistoryEntry.put(transactionRecord); @@ -427,7 +653,7 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON // Serialization JSONObject dataToSend = new JSONObject(); dataToSend.put("bank_id", "01"); - dataToSend.put("user_did", receiverDidIpfsHash); + dataToSend.put("user_did", DID); dataToSend.put("token_id", token); dataToSend.put("level", level); dataToSend.put("denomination", 1); @@ -478,8 +704,8 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON // Serialization JSONObject dataToSend = new JSONObject(); dataToSend.put("transaction_id", tid); - dataToSend.put("sender_did", receiverDidIpfsHash); - dataToSend.put("receiver_did", receiverDidIpfsHash); + dataToSend.put("sender_did", DID); + dataToSend.put("receiver_did", DID); dataToSend.put("token_id", tokenList); dataToSend.put("token_time", (int) totalTime); dataToSend.put("amount", tokenList.size()); @@ -514,7 +740,7 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON ProofCreditsLogger.debug(responseTxn.toString()); } } else { - APIResponse.put("did", receiverDidIpfsHash); + APIResponse.put("did", DID); APIResponse.put("tid", "null"); APIResponse.put("status", "Failed"); APIResponse.put("message", "error from mine service"); @@ -522,7 +748,7 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON return APIResponse; } } else { - APIResponse.put("did", receiverDidIpfsHash); + APIResponse.put("did", DID); APIResponse.put("tid", "null"); APIResponse.put("status", "Failed"); APIResponse.put("message", "Insufficient proofs"); @@ -533,3 +759,5 @@ public static JSONObject create(String data, IPFS ipfs) throws IOException, JSON return APIResponse; } } + +//stakedDIDs diff --git a/src/com/rubix/Ping/PingCheck.java b/src/com/rubix/Ping/PingCheck.java new file mode 100644 index 00000000..e4387711 --- /dev/null +++ b/src/com/rubix/Ping/PingCheck.java @@ -0,0 +1,120 @@ +package com.rubix.Ping; + +import static com.rubix.Resources.Functions.*; +import static com.rubix.Resources.IPFSNetwork.executeIPFSCommands; +import static com.rubix.Resources.IPFSNetwork.forward; +import static com.rubix.Resources.IPFSNetwork.repo; +import static com.rubix.Resources.IPFSNetwork.swarmConnectP2P; + +import io.ipfs.api.IPFS; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.Socket; +import java.net.SocketException; +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.json.JSONException; +import org.json.JSONObject; + + + +public class PingCheck { + private static final Logger PingSenderLogger = Logger.getLogger(PingCheck.class); + public static IPFS ipfs = new IPFS("/ip4/127.0.0.1/tcp/" + IPFS_PORT); + public static BufferedReader serverInput; + + private static int socketTimeOut = 120000; + public static String currentVersion = initHash(); + + public static JSONObject Ping(String peerID, int port) throws IOException, JSONException { + repo(ipfs); + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + PingSenderLogger.debug("Current version in PingSender is "+currentVersion); + + JSONObject APIResponse = new JSONObject(); + if (!peerID.equals("")) { + PingSenderLogger.debug("Swarm connecting to " + peerID); + swarmConnectP2P(peerID, ipfs); + PingSenderLogger.debug("Swarm connected"); + } else { + APIResponse.put("message", "Receiver Peer ID null"); + PingSenderLogger.warn("Receiver Peer ID null"); + return APIResponse; + } + + String receiverWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "peerid", peerID); + String receiverDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", peerID); + if (!receiverWidIpfsHash.equals("")) { + nodeData(receiverDidIpfsHash, receiverWidIpfsHash, ipfs); + } else { + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver WID null"); + PingSenderLogger.warn("Receiver WID null"); + return APIResponse; + } + + PingSenderLogger.debug("Sender IPFS forwarding to DID: " + receiverDidIpfsHash + " PeerID: " + peerID); + String appName = peerID.concat("Ping"); + forward(appName, port, peerID); + PingSenderLogger.debug("Forwarded to " + appName + " on " + port); + Socket senderSocket = new Socket("127.0.0.1", port); + senderSocket.setSoTimeout(0); + BufferedReader input = new BufferedReader(new InputStreamReader(senderSocket.getInputStream())); + PrintStream output = new PrintStream(senderSocket.getOutputStream()); + + output.println("PingCheck"); + PingSenderLogger.debug("Sent PingCheck request"); + + String pongResponse; + try { + pongResponse = input.readLine(); + PingSenderLogger.debug("Pong received is "+pongResponse); + } catch (SocketException e) { + PingSenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Ping Check"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + peerID); + output.close(); + input.close(); + senderSocket.close(); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "is unable to respond! - Sender Auth"); + + return APIResponse; + } + PingSenderLogger.debug("Pong response after pong received "+pongResponse); + if (pongResponse != null) { + PingSenderLogger.debug("Pong response inside pongRespong not null "+pongResponse); + if(pongResponse.contains(currentVersion)) { + PingSenderLogger.debug("Pong response received is "+ pongResponse); + PingSenderLogger.info("Ping Successful"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + peerID); + output.close(); + input.close(); + senderSocket.close(); + APIResponse.put("status", "Success"); + APIResponse.put("message", "Ping Check Success"); + }else { + PingSenderLogger.debug("Receiver is running "+ pongResponse); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + peerID); + output.close(); + input.close(); + senderSocket.close(); + APIResponse.put("status", "Failed"); + APIResponse.put("message", getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", receiverDidIpfsHash)+ " not running new version"); + } + + } else { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + peerID); + PingSenderLogger.info("Pong response not received"); + PingSenderLogger.info("Pong response now received with error is "+pongResponse); + output.close(); + input.close(); + senderSocket.close(); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Pong response not received"); + + } + return APIResponse; + } +} diff --git a/src/com/rubix/Ping/PingReceive.java b/src/com/rubix/Ping/PingReceive.java new file mode 100644 index 00000000..43f28818 --- /dev/null +++ b/src/com/rubix/Ping/PingReceive.java @@ -0,0 +1,159 @@ +package com.rubix.Ping; + +import static com.rubix.Resources.Functions.DATA_PATH; +import static com.rubix.Resources.Functions.IPFS_PORT; +import static com.rubix.Resources.Functions.LOGGER_PATH; +import static com.rubix.Resources.Functions.TOKENCHAIN_PATH; +import static com.rubix.Resources.Functions.getPeerID; +import static com.rubix.Resources.Functions.initHash; +import static com.rubix.Resources.Functions.pathSet; +import static com.rubix.Resources.Functions.readFile; +import static com.rubix.Resources.IPFSNetwork.executeIPFSCommands; +import static com.rubix.Resources.IPFSNetwork.listen; +import static com.rubix.Resources.IPFSNetwork.repo; + +import io.ipfs.api.IPFS; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + + + +public class PingReceive { + public static Logger PingReceiverLogger = Logger.getLogger(PingReceive.class); + + private static final JSONObject APIResponse = new JSONObject(); + private static final IPFS ipfs = new IPFS("/ip4/127.0.0.1/tcp/" + IPFS_PORT); + public static String currentVersion = initHash(); + + /** + * Receiver Node: To receive a valid token from an authentic sender + * + * @return Transaction Details (JSONObject) + * @throws IOException handles IO Exceptions + * @throws JSONException handles JSON Exceptions + */ + public static String receive(String userType,int port) throws JSONException { + pathSet(); + ServerSocket ss; + Socket sk; + + try { + repo(ipfs); + + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + + String receiverPeerID = getPeerID(DATA_PATH + "DID.json"); + String appName = receiverPeerID.concat("Ping"); + listen(appName, port); + ss = new ServerSocket(port); + PingReceiverLogger.debug("Ping "+userType+" Listening on " + port + " appname " + appName); + + sk = ss.accept(); + PingReceiverLogger.debug("Data Incoming..."); + BufferedReader input = new BufferedReader(new InputStreamReader(sk.getInputStream())); + PrintStream output = new PrintStream(sk.getOutputStream()); + + int height = 0; + String pingRequest; + try { + pingRequest = input.readLine(); + } catch (SocketException e) { + PingReceiverLogger.warn("Sender Stream Null - PingCheck"); + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender Stream Null - PingCheck"); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + PingReceiverLogger.debug("Ping Request Received: " + pingRequest); + if (pingRequest != null) { + if(pingRequest.contains("PingCheck")) { + PingReceiverLogger.debug(userType + " Sending version "+currentVersion); + output.println(currentVersion); + PingReceiverLogger.debug(userType + " Sent version to pingSender"+currentVersion); + APIResponse.put("status", "Success"); + APIResponse.put("message", "Pong Sent to Sender with Check Sum"); + PingReceiverLogger.info(userType + " Pong Sent "+currentVersion); + + } + else + if(pingRequest.contains("Get-TokenChain-Height")) { + String tokenHash; + try { + tokenHash = input.readLine(); + } catch (SocketException e) { + PingReceiverLogger.warn("Sender Stream Null - tokenHash"); + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender Stream Null - tokenHash"); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + if (tokenHash != null && tokenHash.startsWith("Qm") && tokenHash.length() == 46) { + PingReceiverLogger.info("Token chain height requested for: " + tokenHash); + File tokenChainFile = new File(TOKENCHAIN_PATH.concat(tokenHash).concat(".json")); + if(!tokenChainFile.exists()) { + PingReceiverLogger.info("Token chain file not found"); + height = 0; + } + else{ + String tokenChain = readFile(TOKENCHAIN_PATH.concat(tokenHash).concat(".json")); + JSONArray chainArray = new JSONArray(tokenChain); + height = chainArray.length()-1; + PingReceiverLogger.info("Chain height: " + height); + } + } + + } + else{ + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Request Failed"); + PingReceiverLogger.info(userType+ " Request Failed"); + } + + APIResponse.put("status", "Success"); + APIResponse.put("message", "Pong Sent"); + PingReceiverLogger.info(userType + " Pong Sent"); + + } + else { + PingReceiverLogger.info("Pong Not Sent "); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Pong Failed"); + PingReceiverLogger.info(userType + " Pong Failed"); + } + executeIPFSCommands(" ipfs p2p close -t /p2p/" + pingRequest); + output.close(); + input.close(); + sk.close(); + ss.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + return APIResponse.toString(); + } +} diff --git a/src/com/rubix/Ping/VerifyStakedToken.java b/src/com/rubix/Ping/VerifyStakedToken.java new file mode 100644 index 00000000..bd599f54 --- /dev/null +++ b/src/com/rubix/Ping/VerifyStakedToken.java @@ -0,0 +1,119 @@ +package com.rubix.Ping; + +import static com.rubix.Resources.Functions.IPFS_PORT; +import static com.rubix.Resources.Functions.LOGGER_PATH; +import static com.rubix.Resources.Functions.SYNC_IP; +import static com.rubix.Resources.IPFSNetwork.executeIPFSCommands; +import static com.rubix.Resources.IPFSNetwork.forward; +import static com.rubix.Resources.IPFSNetwork.repo; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.HttpURLConnection; +import java.net.Socket; +import java.net.SocketException; +import java.net.URL; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.json.JSONException; +import org.json.JSONObject; + +import io.ipfs.api.IPFS; + +public class VerifyStakedToken { + private static final Logger PingSenderLogger = Logger.getLogger(VerifyStakedToken.class); + public static IPFS ipfs = new IPFS("/ip4/127.0.0.1/tcp/" + IPFS_PORT); + + public static boolean Contact(String pid, int port, String tokenHash, String tokenContent) + throws IOException, JSONException { + repo(ipfs); + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + + JSONObject APIResponse = new JSONObject(); + + String appName = pid.concat("Ping"); + forward(appName, port, pid); + PingSenderLogger.debug("Forwarded to " + appName + " on " + port + " for collecting credits"); + Socket senderSocket = new Socket("127.0.0.1", port); + + BufferedReader input = new BufferedReader(new InputStreamReader(senderSocket.getInputStream())); + PrintStream output = new PrintStream(senderSocket.getOutputStream()); + + output.println("Get-TokenChain-Height"); + output.println(tokenHash); + String heightResponse; + try { + heightResponse = input.readLine(); + } catch (SocketException e) { + PingSenderLogger.warn("Quorum " + pid + " is unable to Respond! - Credits Ping"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + pid); + output.close(); + input.close(); + senderSocket.close(); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Quorum " + pid + "is unable to respond! - Credits Ping"); + + return false; + } + + int height = 0; + if (heightResponse == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + pid); + PingSenderLogger.info("TokenChain height not received"); + output.close(); + input.close(); + senderSocket.close(); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "TokenChain height not received"); + + } else { + PingSenderLogger.info("TokenChain height received from " + pid); + PingSenderLogger.info("TokenChain height: " + heightResponse); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + pid); + output.close(); + input.close(); + senderSocket.close(); + APIResponse.put("status", "Success"); + APIResponse.put("message", Integer.parseInt(heightResponse)); + height = Integer.parseInt(heightResponse); + } + + String tokenLevel = tokenContent.substring(0, 3); + int tokenLevelInt = Integer.parseInt(tokenLevel); + int tokenLevelValue = (int) Math.pow(2, tokenLevelInt + 2); + int requiredMinedTokenHeight = tokenLevelValue * 4; + + String GET_URL_credit = SYNC_IP + "/getCurrentLevel"; + URL URLobj_credit = new URL(GET_URL_credit); + HttpURLConnection con_credit = (HttpURLConnection) URLobj_credit.openConnection(); + con_credit.setRequestMethod("GET"); + int responseCode_credit = con_credit.getResponseCode(); + System.out.println("GET Response Code :: " + responseCode_credit); + if (responseCode_credit == HttpURLConnection.HTTP_OK) { + BufferedReader in_credit = new BufferedReader( + new InputStreamReader(con_credit.getInputStream())); + String inputLine_credit; + StringBuffer response_credit = new StringBuffer(); + while ((inputLine_credit = in_credit.readLine()) != null) { + response_credit.append(inputLine_credit); + } + in_credit.close(); + // QuorumConsensusLogger.debug("response from service " + + // response_credit.toString()); + JSONObject resJsonData_credit = new JSONObject(response_credit.toString()); + int level_credit = resJsonData_credit.getInt("level"); + + // ! release staked token if the mined token is from previous level(s) + if (level_credit > tokenLevelInt) { + return true; + } + + } else + PingSenderLogger.debug("GET request not worked"); + + return height > requiredMinedTokenHeight; + } +} \ No newline at end of file diff --git a/src/com/rubix/Resources/APIHandler.java b/src/com/rubix/Resources/APIHandler.java index 14e22c13..c2fdf08b 100644 --- a/src/com/rubix/Resources/APIHandler.java +++ b/src/com/rubix/Resources/APIHandler.java @@ -135,42 +135,202 @@ public static JSONObject create(int type) throws Exception { } /** - * A call to get details of a transaction given its ID + * A method to add and host your DID ans Public share to ipfs * - * @param txnId - * @return Transaction Details - * @throws JSONException handles JSON Exceptions + * @files DID.json, DataTable.json, DID.png, PublicShare.png */ - public static JSONArray transactionDetails(String txnId) throws JSONException { - String transactionHistory = readFile(WALLET_DATA_PATH + "TransactionHistory.json"); - JSONObject countResult = new JSONObject(); + public static void addPublicData() { + String peerID = getPeerID(DATA_PATH + "DID.json"); + String didHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", peerID); + String walletHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "peerid", peerID); + + add(DATA_PATH.concat(didHash).concat("/DID.png"), ipfs); + pin(didHash, ipfs); + + add(DATA_PATH.concat(didHash).concat("/PublicShare.png"), ipfs); + pin(walletHash, ipfs); + + } + + /** + * A call to sync all the nodes in the network + * + * @return Message if failed or succeeded + * @throws IOException + * @files DataTable.json + */ + public static String networkInfo() throws IOException, JSONException { + StringBuilder result = new StringBuilder(); JSONArray resultArray = new JSONArray(); - if (transactionHistory.length() == 0) { - countResult.put("Message", "No transactions found"); - resultArray.put(countResult); - return resultArray; + JSONObject jsonObject = new JSONObject(); + int syncFlag = 0; + URL url = new URL(SYNC_IP + "/get"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + + while ((line = rd.readLine()) != null) { + result.append(line); + syncFlag = 1; } - JSONArray transArray = new JSONArray(transactionHistory); - JSONObject obj = new JSONObject(); - for (int i = 0; i < transArray.length(); i++) { - obj = transArray.getJSONObject(i); - if (obj.get("txn").equals(txnId)) { - obj.remove("essentialShare"); + rd.close(); - if (obj.has("amount")) - obj.put("amount", obj.getDouble("amount")); - else { - JSONArray tokensArray = (JSONArray) obj.get("tokens"); - obj.put("amount", tokensArray.length()); - } + writeToFile(DATA_PATH + "DataTable.json", result.toString(), false); + if (syncFlag == 1) { + jsonObject.put("message", "Synced Successfully!"); + } else { + jsonObject.put("message", "Not synced! Try again after sometime."); + } + resultArray.put(jsonObject); + return resultArray.toString(); + } + + /** + * Method to query the credits information + * + * @throws JSONException + * @files QuorumSignedTransactions.json, MinedCreditsHistory.json + */ + public static JSONObject creditsInfo() throws JSONException { + String qstFile = WALLET_DATA_PATH.concat("QuorumSignedTransactions.json"); + String mineFile = WALLET_DATA_PATH.concat("MinedCreditsHistory.json"); + + File quorumFile = new File(qstFile); + File minedFile = new File(mineFile); + + int spentCredits = 0; + int unspentCredits = 0; + if (quorumFile.exists()) { + String qFile = readFile(qstFile); + JSONArray qArray = new JSONArray(qFile); + unspentCredits = qArray.length(); + } + if (minedFile.exists()) { + String mFile = readFile(mineFile); + JSONArray mArray = new JSONArray(mFile); + spentCredits = mArray.length(); + } + + JSONObject returnObject = new JSONObject(); + returnObject.put("spentCredits", spentCredits); + returnObject.put("unspentCredits", unspentCredits); + + return returnObject; + } + + /** + * A call to close all open IPFS streams + */ + public static void closeStreams() { + executeIPFSCommands("ipfs p2p close --all"); + } + + public static int onlinePeersCount() throws JSONException, IOException, InterruptedException { + JSONArray peersArray = peersOnlineStatus(); + int count = 0; + for (int i = 0; i < peersArray.length(); i++) { + if (peersArray.getJSONObject(i).getString("onlineStatus").contains("online")) + count++; + } + return count; + } + + public static ArrayList swarmPeersList() throws IOException, InterruptedException { + String OS = getOsName(); + String[] command = new String[3]; + if (OS.contains("Mac") || OS.contains("Linux")) { + command[0] = "bash"; + command[1] = "-c"; + } else if (OS.contains("Windows")) { + command[0] = "cmd.exe"; + command[1] = "/c"; + } + command[2] = "export PATH=/usr/local/bin:$PATH && ipfs swarm peers"; + + Process P = Runtime.getRuntime().exec(command); + BufferedReader br = new BufferedReader(new InputStreamReader(P.getInputStream())); + + ArrayList peersArray = new ArrayList(); + String line; + while ((line = br.readLine()) != null) { + peersArray.add(line); + } + if (!OS.contains("Windows")) + P.waitFor(); + br.close(); + P.destroy(); + + ArrayList peersIdentities = new ArrayList(); + if (peersArray.size() != 0) { + List k = ipfs.swarm.peers(); + for (int i = 0; i < k.size(); i++) + peersIdentities.add(k.get(i).toString().substring(0, 46)); + + return peersIdentities; + } + return peersArray; + } + + /** + * A call to get the online/offline status of your contacts + * + * @return List indicating online status of each DID contact + * @throws JSONException handles JSON Exceptions + * @throws IOException handles IO Exceptions + */ + public static JSONArray peersOnlineStatus() throws JSONException, IOException, InterruptedException { + ArrayList peersArray = swarmPeersList(); + String dataTable = readFile(DATA_PATH + "DataTable.json"); + JSONArray dataArray = new JSONArray(dataTable); + JSONArray onlinePeers = new JSONArray(); - resultArray.put(obj); + for (int i = 0; i < dataArray.length(); i++) { + JSONObject peerObject = dataArray.getJSONObject(i); + String peerID = peerObject.getString("peerid"); + if (peersArray.contains(peerID)) { + JSONObject onlinePeersObject = new JSONObject(); + onlinePeersObject.put("did", getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", peerID)); + onlinePeersObject.put("onlineStatus", "online"); + onlinePeers.put(onlinePeersObject); + } else { + JSONObject onlinePeersObject = new JSONObject(); + onlinePeersObject.put("did", getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", peerID)); + onlinePeersObject.put("onlineStatus", "offline"); + onlinePeers.put(onlinePeersObject); } } - APILogger.info("Transaction Details for : " + obj.toString()); - return resultArray; + + return onlinePeers; + } + + /** + * A call to list out all contacts in the user wallet + * + * @return A list of user wallet contacts + * @throws JSONException handles JSON Exceptions + */ + public static JSONArray contacts() throws JSONException { + String dataTable = readFile(DATA_PATH + "DataTable.json"); + JSONArray dataArray = new JSONArray(dataTable); + JSONArray didArray = new JSONArray(); + for (int i = 0; i < dataArray.length(); i++) { + didArray.put(dataArray.getJSONObject(i).getString("didHash")); + } + return didArray; + } + + public static JSONObject syncNetworkNodes() throws JSONException, IOException { + String dataTable = readFile(DATA_PATH + "DataTable.json"); + JSONArray dataArray = new JSONArray(dataTable); + + for (int i = 0; i < dataArray.length(); i++) + nodeData(dataArray.getJSONObject(i).getString("didHash"), + dataArray.getJSONObject(i).getString("walletHash"), ipfs); + + return new JSONObject("{\"message\":\"Synced all nodes\"}"); } /** @@ -178,6 +338,7 @@ public static JSONArray transactionDetails(String txnId) throws JSONException { * * @return Detailed explanation of the account information of the user * @throws JSONException handles JSON Exceptions + * @files TransactionHistory.json, DID.json */ public static JSONArray accountInformation() throws JSONException { int txnAsSender = 0, txnAsReceiver = 0; @@ -219,53 +380,80 @@ public static JSONArray accountInformation() throws JSONException { } /** - * A method to add and host your DID ans Public share to ipfs + * A call to list out number of transactions made per day + * + * @return List of transactions committed on every date + * @throws JSONException handles JSON Exceptions + * @files TransactionHistory.json */ - public static void addPublicData() { - String peerID = getPeerID(DATA_PATH + "DID.json"); - String didHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", peerID); - String walletHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "peerid", peerID); + public static JSONArray txnPerDay() throws JSONException { + String dataTableFileContent = readFile(WALLET_DATA_PATH + "TransactionHistory.json"); + JSONArray dataTable = new JSONArray(dataTableFileContent); + HashSet dateSet = new HashSet<>(); + for (int i = 0; i < dataTable.length(); i++) + dateSet.add(dataTable.getJSONObject(i).getString("Date")); - add(DATA_PATH.concat(didHash).concat("/DID.png"), ipfs); - pin(didHash, ipfs); + JSONObject datesTxn = new JSONObject(); + Iterator dateIterator = dateSet.iterator(); + while (dateIterator.hasNext()) { + String date = dateIterator.next(); + int count = 0; + for (int i = 0; i < dataTable.length(); i++) { + JSONObject obj = dataTable.getJSONObject(i); - add(DATA_PATH.concat(didHash).concat("/PublicShare.png"), ipfs); - pin(walletHash, ipfs); + if (date.equals(obj.getString("Date"))) { + count++; + } + } + datesTxn.put(date, count); + } + + return new JSONArray().put(datesTxn); } /** - * A call to sync all the nodes in the network + * A call to get details of a transaction given its ID * - * @return Message if failed or succeeded - * @throws IOException + * @param txnId Transaction ID + * @return Transaction Details + * @throws JSONException handles JSON Exceptions + * @files TransactionHistory.json */ - public static String networkInfo() throws IOException, JSONException { - StringBuilder result = new StringBuilder(); + public static JSONArray transactionDetails(String txnId) throws JSONException { + String transactionHistory = readFile(WALLET_DATA_PATH + "TransactionHistory.json"); + JSONObject countResult = new JSONObject(); JSONArray resultArray = new JSONArray(); - JSONObject jsonObject = new JSONObject(); - int syncFlag = 0; - URL url = new URL(SYNC_IP + "/get"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod("GET"); - BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); - String line; - - while ((line = rd.readLine()) != null) { - result.append(line); - syncFlag = 1; + if (transactionHistory.length() == 0) { + countResult.put("Message", "No transactions found"); + resultArray.put(countResult); + return resultArray; } - rd.close(); + JSONArray transactionArray = new JSONArray(transactionHistory); + JSONObject transactionObject = new JSONObject(); + for (int i = 0; i < transactionArray.length(); i++) { + transactionObject = transactionArray.getJSONObject(i); + if (transactionObject.get("txn").equals(txnId)) { + transactionObject.remove("essentialShare"); + + if (transactionObject.has("amount-received")) { + transactionObject.put("amount", transactionObject.getDouble("amount-received")); + } else if (transactionObject.has("amount-spent")) { + transactionObject.put("amount", transactionObject.getDouble("amount-spent")); + } else if (transactionObject.has("amount")) + transactionObject.put("amount", transactionObject.getDouble("amount")); + else { + JSONArray tokensArray = (JSONArray) transactionObject.get("tokens"); + transactionObject.put("amount", tokensArray.length()); + } + + resultArray.put(transactionObject); + } - writeToFile(DATA_PATH + "DataTable.json", result.toString(), false); - if (syncFlag == 1) { - jsonObject.put("message", "Synced Successfully!"); - } else { - jsonObject.put("message", "Not synced! Try again after sometime."); } - resultArray.put(jsonObject); - return resultArray.toString(); + APILogger.info("Transaction Details for : " + transactionObject.toString()); + return resultArray; } /** @@ -275,6 +463,7 @@ public static String networkInfo() throws IOException, JSONException { * @param e End Date * @return List of transactions * @throws JSONException handles JSON Exceptions + * @files TransactionHistory.json */ public static JSONArray transactionsByDate(String s, String e) throws JSONException, ParseException { JSONArray resultArray = new JSONArray(); @@ -287,8 +476,6 @@ public static JSONArray transactionsByDate(String s, String e) throws JSONExcept JSONObject countResult = new JSONObject(); Date startDate = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss").parse(startDateString); Date endDate = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss").parse(endDateString); - APILogger.debug("start date is " + startDate); - APILogger.debug("end date is " + endDate); File fileCheck1 = new File(WALLET_DATA_PATH + "TransactionHistory.json"); if (!fileCheck1.exists()) { countResult.put("Message", "File not found"); @@ -297,32 +484,37 @@ public static JSONArray transactionsByDate(String s, String e) throws JSONExcept } String transactionHistory = readFile(WALLET_DATA_PATH + "TransactionHistory.json"); JSONArray transArray = new JSONArray(transactionHistory); - APILogger.debug(transArray.length()); if (transArray.length() == 0) { countResult.put("Message", "No Transactions made yet"); resultArray.put(countResult); return resultArray; } - JSONObject obj; + JSONObject transactionObject; for (int i = 0; i < transArray.length(); i++) { - obj = transArray.getJSONObject(i); - String dateFromTxnHistoryString = obj.get("Date").toString(); - Date dateTH = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy").parse(dateFromTxnHistoryString); - String dateTHS = objSDF.format(dateTH); - Calendar c = Calendar.getInstance(); - c.setTime(objSDF.parse(dateTHS)); - dateTH = c.getTime(); - if (dateTH.after(startDate) && dateTH.before(endDate)) { - obj.remove("essentialShare"); - - if (obj.has("amount")) - obj.put("amount", obj.getDouble("amount")); - else { - JSONArray tokensArray = (JSONArray) obj.get("tokens"); - obj.put("amount", tokensArray.length()); + transactionObject = transArray.getJSONObject(i); + String dateFromTxnHistoryString = transactionObject.get("Date").toString(); + if (dateFromTxnHistoryString.length() != 10) { + Date dateTH = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy").parse(dateFromTxnHistoryString); + String dateTHS = objSDF.format(dateTH); + Calendar c = Calendar.getInstance(); + c.setTime(objSDF.parse(dateTHS)); + dateTH = c.getTime(); + if (dateTH.after(startDate) && dateTH.before(endDate)) { + transactionObject.remove("essentialShare"); + + if (transactionObject.has("amount-received")) { + transactionObject.put("amount", transactionObject.getDouble("amount-received")); + } else if (transactionObject.has("amount-spent")) { + transactionObject.put("amount", transactionObject.getDouble("amount-spent")); + } else if (transactionObject.has("amount")) + transactionObject.put("amount", transactionObject.getDouble("amount")); + else { + JSONArray tokensArray = (JSONArray) transactionObject.get("tokens"); + transactionObject.put("amount", tokensArray.length()); + } + + resultArray.put(transactionObject); } - - resultArray.put(obj); } } @@ -335,6 +527,7 @@ public static JSONArray transactionsByDate(String s, String e) throws JSONExcept * @param n Count * @return List of transactions * @throws JSONException handles JSON Exceptions + * @files TransactionHistory.json */ public static JSONArray transactionsByCount(int n) throws JSONException { @@ -351,7 +544,7 @@ public static JSONArray transactionsByCount(int n) throws JSONException { } String transactionHistory = readFile(path); JSONArray transArray = new JSONArray(transactionHistory); - JSONObject obj = new JSONObject(); + JSONObject transactionObject; if (transArray.length() == 0) { countResult.put("Message", "No transactions made yet"); resultArray.put(countResult); @@ -360,31 +553,39 @@ public static JSONArray transactionsByCount(int n) throws JSONException { if (n >= transArray.length()) { for (int i = transArray.length() - 1; i >= 0; i--) { - obj = transArray.getJSONObject(i); - obj.remove("essentialShare"); - if (obj.has("amount")) - obj.put("amount", obj.getDouble("amount")); + transactionObject = transArray.getJSONObject(i); + transactionObject.remove("essentialShare"); + if (transactionObject.has("amount-received")) { + transactionObject.put("amount", transactionObject.getDouble("amount-received")); + } else if (transactionObject.has("amount-spent")) { + transactionObject.put("amount", transactionObject.getDouble("amount-spent")); + } else if (transactionObject.has("amount")) + transactionObject.put("amount", transactionObject.getDouble("amount")); else { - JSONArray tokensArray = (JSONArray) obj.get("tokens"); - obj.put("amount", tokensArray.length()); + JSONArray tokensArray = (JSONArray) transactionObject.get("tokens"); + transactionObject.put("amount", tokensArray.length()); } - resultArray.put(obj); + resultArray.put(transactionObject); } return resultArray; } for (int i = 1; i <= n; i++) { - obj = transArray.getJSONObject(transArray.length() - i); - obj.remove("essentialShare"); - if (obj.has("amount")) - obj.put("amount", obj.getDouble("amount")); + transactionObject = transArray.getJSONObject(transArray.length() - i); + transactionObject.remove("essentialShare"); + if (transactionObject.has("amount-received")) { + transactionObject.put("amount", transactionObject.getDouble("amount-received")); + } else if (transactionObject.has("amount-spent")) { + transactionObject.put("amount", transactionObject.getDouble("amount-spent")); + } else if (transactionObject.has("amount")) + transactionObject.put("amount", transactionObject.getDouble("amount")); else { - JSONArray tokensArray = (JSONArray) obj.get("tokens"); - obj.put("amount", tokensArray.length()); + JSONArray tokensArray = (JSONArray) transactionObject.get("tokens"); + transactionObject.put("amount", tokensArray.length()); } - resultArray.put(obj); + resultArray.put(transactionObject); } return resultArray; } @@ -396,11 +597,12 @@ public static JSONArray transactionsByCount(int n) throws JSONException { * @param end end index * @return List of transactions * @throws JSONException handles JSON Exceptions + * @files TransactionHistory.json */ public static JSONArray transactionsByRange(int start, int end) throws JSONException { JSONObject countResult = new JSONObject(); JSONArray resultArray = new JSONArray(); - if (start <= 0 || end <= 0) { + if (start < 0 || end <= 0) { countResult.put("Message", "Count can't be null or negative"); resultArray.put(countResult); return resultArray; @@ -427,122 +629,89 @@ public static JSONArray transactionsByRange(int start, int end) throws JSONExcep if (!(end < transArray.length())) { for (int i = start; i < transArray.length(); i++) { - JSONObject obj = transArray.getJSONObject(i); - obj.remove("essentialShare"); - if (obj.has("amount")) - obj.put("amount", obj.getDouble("amount")); + JSONObject transactionObject = transArray.getJSONObject(i); + transactionObject.remove("essentialShare"); + if (transactionObject.has("amount-received")) { + transactionObject.put("amount", transactionObject.getDouble("amount-received")); + } else if (transactionObject.has("amount-spent")) { + transactionObject.put("amount", transactionObject.getDouble("amount-spent")); + } else if (transactionObject.has("amount")) + transactionObject.put("amount", transactionObject.getDouble("amount")); else { - JSONArray tokensArray = (JSONArray) obj.get("tokens"); - obj.put("amount", tokensArray.length()); + JSONArray tokensArray = (JSONArray) transactionObject.get("tokens"); + transactionObject.put("amount", tokensArray.length()); } - resultArray.put(obj); + resultArray.put(transactionObject); } } else { if (start == end) { - JSONObject obj = transArray.getJSONObject(start); - obj.remove("essentialShare"); - if (obj.has("amount")) - obj.put("amount", obj.getDouble("amount")); + JSONObject transactionObject = transArray.getJSONObject(start); + transactionObject.remove("essentialShare"); + if (transactionObject.has("amount-received")) { + transactionObject.put("amount", transactionObject.getDouble("amount-received")); + } else if (transactionObject.has("amount-spent")) { + transactionObject.put("amount", transactionObject.getDouble("amount-spent")); + } else if (transactionObject.has("amount")) + transactionObject.put("amount", transactionObject.getDouble("amount")); else { - JSONArray tokensArray = (JSONArray) obj.get("tokens"); - obj.put("amount", tokensArray.length()); + JSONArray tokensArray = (JSONArray) transactionObject.get("tokens"); + transactionObject.put("amount", tokensArray.length()); } - resultArray.put(obj); - } - for (int i = start; i < end; i++) { - JSONObject obj = transArray.getJSONObject(i); - obj.remove("essentialShare"); - if (obj.has("amount")) - obj.put("amount", obj.getDouble("amount")); - else { - JSONArray tokensArray = (JSONArray) obj.get("tokens"); - obj.put("amount", tokensArray.length()); + resultArray.put(transactionObject); + } else { + for (int i = start; i <= end; i++) { + JSONObject transactionObject = transArray.getJSONObject(i); + transactionObject.remove("essentialShare"); + if (transactionObject.has("amount-received")) { + transactionObject.put("amount", transactionObject.getDouble("amount-received")); + } else if (transactionObject.has("amount-spent")) { + transactionObject.put("amount", transactionObject.getDouble("amount-spent")); + } else if (transactionObject.has("amount")) + transactionObject.put("amount", transactionObject.getDouble("amount")); + else { + JSONArray tokensArray = (JSONArray) transactionObject.get("tokens"); + transactionObject.put("amount", tokensArray.length()); + } + resultArray.put(transactionObject); } - - resultArray.put(obj); } } return resultArray; } - /** - * @throws JSONException - * - */ - public static JSONObject creditsInfo() throws JSONException { - // String thFile = WALLET_DATA_PATH.concat("TransactionHistory.json"); - String qstFile = WALLET_DATA_PATH.concat("QuorumSignedTransactions.json"); - String mineFile = WALLET_DATA_PATH.concat("MinedCreditsHistory.json"); - - // File txnFile = new File(thFile); - File quorumFile = new File(qstFile); - File minedFile = new File(mineFile); - - // int txnCount = 0; - // if(txnFile.exists()){ - // String transactionFile = - // readFile(WALLET_DATA_PATH.concat("TransactionHistory.json")); - // JSONArray txnArray = new JSONArray(transactionFile); - // txnCount = txnArray.length(); - // - // } - int spentCredits = 0; - int unspentCredits = 0; - if (quorumFile.exists()) { - String qFile = readFile(qstFile); - JSONArray qArray = new JSONArray(qFile); - unspentCredits = qArray.length(); - } - if (minedFile.exists()) { - String mFile = readFile(mineFile); - JSONArray mArray = new JSONArray(mFile); - spentCredits = mArray.length(); - } - - JSONObject returnObject = new JSONObject(); - // returnObject.put("txnCount",txnCount); - returnObject.put("spentCredits", spentCredits); - returnObject.put("unspentCredits", unspentCredits); - - return returnObject; - } - - /** - * A call to close all open IPFS streams - */ - public static void closeStreams() { - executeIPFSCommands("ipfs p2p close --all"); - } - /** * A call to get list transactions with the mentioned comment * * @param comment Comment * @return List of transactions * @throws JSONException handles JSON Exceptions + * @files TransactionHistory.json */ public static JSONArray transactionsByComment(String comment) throws JSONException { String transactionHistory = readFile(WALLET_DATA_PATH + "TransactionHistory.json"); JSONArray transArray = new JSONArray(transactionHistory); - JSONObject obj; + JSONObject transactionObject; JSONArray resultArray = new JSONArray(); for (int i = 0; i < transArray.length(); i++) { - obj = transArray.getJSONObject(i); - - if (obj.get("comment").equals(comment)) { - obj.remove("essentialShare"); - if (obj.has("amount")) - obj.put("amount", obj.getDouble("amount")); + transactionObject = transArray.getJSONObject(i); + + if (transactionObject.get("comment").equals(comment)) { + transactionObject.remove("essentialShare"); + if (transactionObject.has("amount-received")) { + transactionObject.put("amount", transactionObject.getDouble("amount-received")); + } else if (transactionObject.has("amount-spent")) { + transactionObject.put("amount", transactionObject.getDouble("amount-spent")); + } else if (transactionObject.has("amount")) + transactionObject.put("amount", transactionObject.getDouble("amount")); else { - JSONArray tokensArray = (JSONArray) obj.get("tokens"); - obj.put("amount", tokensArray.length()); + JSONArray tokensArray = (JSONArray) transactionObject.get("tokens"); + transactionObject.put("amount", tokensArray.length()); } - - resultArray.put(obj); + resultArray.put(transactionObject); } } @@ -561,166 +730,108 @@ public static JSONArray transactionsByComment(String comment) throws JSONExcepti * @param did DID of the contact * @return List of transactions committed with the user DID * @throws JSONException handles JSON Exceptions + * @files TransactionHistory.json */ public static JSONArray transactionsByDID(String did) throws JSONException { String transactionHistory = readFile(WALLET_DATA_PATH + "TransactionHistory.json"); JSONArray transArray = new JSONArray(transactionHistory); JSONArray resultArray = new JSONArray(); for (int i = 0; i < transArray.length(); i++) { - JSONObject obj = transArray.getJSONObject(i); - obj.remove("essentialShare"); + JSONObject transactionObject = transArray.getJSONObject(i); + transactionObject.remove("essentialShare"); + + if (transactionObject.get("senderDID").equals(did) || transactionObject.get("receiverDID").equals(did)) { + if (transactionObject.has("amount-received")) { + transactionObject.put("amount", transactionObject.getDouble("amount-received")); + } else if (transactionObject.has("amount-spent")) { + transactionObject.put("amount", transactionObject.getDouble("amount-spent")); + } else if (transactionObject.has("amount")) + transactionObject.put("amount", transactionObject.getDouble("amount")); + else { + JSONArray tokensArray = (JSONArray) transactionObject.get("tokens"); + transactionObject.put("amount", tokensArray.length()); + } - if (obj.has("amount")) - obj.put("amount", obj.getDouble("amount")); - else { - JSONArray tokensArray = (JSONArray) obj.get("tokens"); - obj.put("amount", tokensArray.length()); + resultArray.put(transactionObject); } - - resultArray.put(obj); - - if (obj.get("senderDID").equals(did) || obj.get("receiverDID").equals(did)) - resultArray.put(obj); } return resultArray; } - - public static int onlinePeersCount() throws JSONException, IOException, InterruptedException { - JSONArray peersArray = peersOnlineStatus(); - int count = 0; - for (int i = 0; i < peersArray.length(); i++) { - if (peersArray.getJSONObject(i).getString("onlineStatus").contains("online")) - count++; - } - return count; - } - - public static ArrayList swarmPeersList() throws IOException, InterruptedException { - String OS = getOsName(); - String[] command = new String[3]; - if (OS.contains("Mac") || OS.contains("Linux")) { - command[0] = "bash"; - command[1] = "-c"; - } else if (OS.contains("Windows")) { - command[0] = "cmd.exe"; - command[1] = "/c"; - } - command[2] = "export PATH=/usr/local/bin:$PATH && ipfs swarm peers"; - - Process P = Runtime.getRuntime().exec(command); - BufferedReader br = new BufferedReader(new InputStreamReader(P.getInputStream())); - - ArrayList peersArray = new ArrayList(); - String line; - while ((line = br.readLine()) != null) { - peersArray.add(line); - } - if (!OS.contains("Windows")) - P.waitFor(); - br.close(); - P.destroy(); - - ArrayList peersIdentities = new ArrayList(); - if (peersArray.size() != 0) { - List k = ipfs.swarm.peers(); - for (int i = 0; i < k.size(); i++) - peersIdentities.add(k.get(i).toString().substring(0, 46)); - - return peersIdentities; - } - return peersArray; - } - + /** - * A call to get the online/offline status of your contacts + * A call to generate hashtable in node * - * @return List indicating online status of each DID contact - * @throws JSONException handles JSON Exceptions - * @throws IOException handles IO Exceptions + * @return Message if failed or succeeded + * @throws JSONException + * @throws InterruptedException + * @files TokenHashTable.json */ - public static JSONArray peersOnlineStatus() throws JSONException, IOException, InterruptedException { - ArrayList peersArray = swarmPeersList(); - String dataTable = readFile(DATA_PATH + "DataTable.json"); - JSONArray dataArray = new JSONArray(dataTable); - JSONArray onlinePeers = new JSONArray(); - - for (int i = 0; i < dataArray.length(); i++) { - JSONObject peerObject = dataArray.getJSONObject(i); - String peerID = peerObject.getString("peerid"); - if (peersArray.contains(peerID)) { - JSONObject onlinePeersObject = new JSONObject(); - onlinePeersObject.put("did", getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", peerID)); - onlinePeersObject.put("onlineStatus", "online"); - onlinePeers.put(onlinePeersObject); - } else { - JSONObject onlinePeersObject = new JSONObject(); - onlinePeersObject.put("did", getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", peerID)); - onlinePeersObject.put("onlineStatus", "offline"); - onlinePeers.put(onlinePeersObject); - } - + public static JSONArray tokenHashTableGeneration() throws JSONException, InterruptedException { + System.out.println("API Handler - generting hash table"); + StringBuilder result = new StringBuilder(); + JSONArray resultArray = new JSONArray(); + JSONObject jsonObject = new JSONObject(); + boolean generationStatus = false; + File tokenHashTable = new File(DATA_PATH.concat("DataHash")); + System.out.println("File path is "+ tokenHashTable.toString()); + generationStatus = Functions.generateMultiLoopWithHashMap(tokenHashTable.toString()); + + if (generationStatus == true && (tokenHashTable.exists() && (tokenHashTable.length() / (1024 * 1024))>0)) { + jsonObject.put("message", "Token Hash Table Generation successful"); + } else { + jsonObject.put("message", "Unable to generate Token Hash Table! Try again after sometime."); } - - return onlinePeers; + resultArray.put(jsonObject); + return resultArray; } - + /** - * A call to list out all contacts in the user wallet + * This method is to get the no. of staked tokens * - * @return A list of user wallet contacts + * @param + * @return no. of staked token * @throws JSONException handles JSON Exceptions - */ - public static JSONArray contacts() throws JSONException { - String dataTable = readFile(DATA_PATH + "DataTable.json"); - JSONArray dataArray = new JSONArray(dataTable); - JSONArray didArray = new JSONArray(); - for (int i = 0; i < dataArray.length(); i++) { - didArray.put(dataArray.getJSONObject(i).getString("didHash")); - } - return didArray; - } - + * @files + */ + public static int stakedTokencount() throws JSONException { + String stakedtokens = Functions.WALLET_DATA_PATH.concat("Stake/"); + int count =0; + File stkedtokensfile = new File(stakedtokens); + File[] filesList = stkedtokensfile.listFiles(); + if (stkedtokensfile.exists()) { + for ( File file : filesList) { + String sFile = file.getName(); + String k = stakedtokens+sFile; + String contactsFile = Functions.readFile(k); + + JSONObject js = new JSONObject(contactsFile); + + JSONObject stakedata = js.getJSONObject("stakeData"); + String staked_mineid = stakedata.getString("stakedToken"); + count++; + } + } + return count; + } + /** - * A call to list out number of transactions made per day + * This method is to get the withdrawal balance * - * @return List of transactions committed on every date + * @param + * @return withdrawal balance * @throws JSONException handles JSON Exceptions - */ - public static JSONArray txnPerDay() throws JSONException { - String dataTable = readFile(WALLET_DATA_PATH + "TransactionHistory.json"); - JSONArray dataArray = new JSONArray(dataTable); - HashSet dateSet = new HashSet<>(); - for (int i = 0; i < dataArray.length(); i++) - dateSet.add(dataArray.getJSONObject(i).getString("Date")); - - JSONObject datesTxn = new JSONObject(); - Iterator dateIterator = dateSet.iterator(); - while (dateIterator.hasNext()) { - String date = dateIterator.next(); - int count = 0; - for (int i = 0; i < dataArray.length(); i++) { - JSONObject obj = dataArray.getJSONObject(i); - - if (date.equals(obj.getString("Date"))) { - count++; - } - } - datesTxn.put(date, count); - - } - - return new JSONArray().put(datesTxn); + * @files + */ + public static Double getAvailableBalance() throws JSONException, IOException + { + int stakedtokens=APIHandler.stakedTokencount(); + Double balance=Functions.getBalance(); + + Double availablebalance = balance - stakedtokens; + + return availablebalance; + } - public static JSONObject syncNetworkNodes() throws JSONException, IOException { - String dataTable = readFile(DATA_PATH + "DataTable.json"); - JSONArray dataArray = new JSONArray(dataTable); - - for (int i = 0; i < dataArray.length(); i++) - nodeData(dataArray.getJSONObject(i).getString("didHash"), - dataArray.getJSONObject(i).getString("walletHash"), ipfs); - - return new JSONObject("{\"message\":\"Synced all nodes\"}"); - } } diff --git a/src/com/rubix/Resources/Functions.java b/src/com/rubix/Resources/Functions.java index e03ff34c..8f74ec90 100644 --- a/src/com/rubix/Resources/Functions.java +++ b/src/com/rubix/Resources/Functions.java @@ -1,11 +1,18 @@ package com.rubix.Resources; import static com.rubix.Resources.APIHandler.addPublicData; +import static com.rubix.Resources.Functions.LOGGER_PATH; +import static com.rubix.Resources.Functions.calculateHash; +import static com.rubix.Resources.Functions.deleteFile; +import static com.rubix.Resources.Functions.formatAmount; +import static com.rubix.Resources.Functions.writeToFile; +import static com.rubix.Resources.IPFSNetwork.IPFSNetworkLogger; import static com.rubix.Resources.IPFSNetwork.checkSwarmConnect; -import static com.rubix.Resources.IPFSNetwork.dhtOwnerCheck; import static com.rubix.Resources.IPFSNetwork.executeIPFSCommands; import static com.rubix.Resources.IPFSNetwork.forwardCheck; import static com.rubix.Resources.IPFSNetwork.listen; +import static com.rubix.Resources.IPFSNetwork.swarmConnectP2P; +import static com.rubix.Resources.IPFSNetwork.swarmConnectProcess; import java.awt.image.BufferedImage; import java.io.BufferedReader; @@ -16,9 +23,13 @@ import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; +import java.io.RandomAccessFile; import java.math.RoundingMode; import java.net.HttpURLConnection; +import java.net.MalformedURLException; import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; @@ -28,20 +39,33 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.*; +import java.util.stream.*; import javax.imageio.ImageIO; +import javax.json.JsonArray; import com.rubix.AuthenticateNode.PropImage; +import com.rubix.Ping.PingCheck; -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; +import org.apache.log4j.*; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import io.ipfs.api.IPFS; +import io.ipfs.multiaddr.MultiAddress; public class Functions { @@ -70,37 +94,6 @@ public class Functions { public static Logger FunctionsLogger = Logger.getLogger(Functions.class); - public static String buildVersion() throws IOException { - String initPath = Functions.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - initPath = initPath.split("\\.jar")[0]; - initPath = initPath + ".jar"; - String initHash = calculateFileHash(initPath, "MD5"); - return initHash; - } - - public static String calculateFileHash(String filePath, String algorithm) { - String hash = ""; - try { - MessageDigest digest = MessageDigest.getInstance(algorithm); - System.out.println("File path: " + filePath); - System.out.println("File Hashing..."); - FileInputStream fis = new FileInputStream(filePath); - System.out.println("File read OK"); - byte[] dataBytes = new byte[1024]; - int nread = 0; - while ((nread = fis.read(dataBytes)) != -1) { - digest.update(dataBytes, 0, nread); - } - byte[] hashBytes = digest.digest(); - hash = bytesToHex(hashBytes); - fis.close(); - } catch (NoSuchAlgorithmException | IOException e) { - FunctionsLogger.error("Invalid Cryptographic Algorithm", e); - e.printStackTrace(); - } - return hash; - } - public static void setDir() { String OSName = getOsName(); if (OSName.contains("Windows")) @@ -118,6 +111,43 @@ public static void setConfig() { configPath = dirPath.concat("config.json"); } + public static String buildVersion() throws IOException { + String jarPath = Functions.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + jarPath = jarPath.split("\\.jar")[0]; + jarPath = jarPath.split("file:", 2)[1]; + // trim first part of the string till first "/" + + jarPath = jarPath + ".jar"; + String hash = calculateFileHash(jarPath, "MD5"); + return hash; + } + + public static String calculateFileHash(String filePath, String algorithm) { + String hash = ""; + try { + MessageDigest digest = MessageDigest.getInstance(algorithm); + System.out.println("File path: " + filePath); + + // check if file exists at the filePath + File file = new File(filePath); + if (file.exists()) { + FileInputStream fis = new FileInputStream(file); + byte[] byteArray = new byte[1024]; + int bytesCount = 0; + while ((bytesCount = fis.read(byteArray)) != -1) { + digest.update(byteArray, 0, bytesCount); + } + byte[] hashBytes = digest.digest(); + hash = bytesToHex(hashBytes); + fis.close(); + } + } catch (NoSuchAlgorithmException | IOException e) { + FunctionsLogger.error("Invalid Cryptographic Algorithm while calculating file hash", e); + e.printStackTrace(); + } + return hash; + } + /** * This method sets the required paths used in the functions */ @@ -431,29 +461,6 @@ public static void listenThread(JSONObject connectObject) { } - /** - * This function check if the token is pinned by the given DID - * - * @param token ID and DID of owner of the token to be checked - * @return boolean value - */ - public static boolean checkTokenOwnershiByDID(String tokenID, String DID) { - boolean ownStatus = false; - String peerID = getValues(DATA_PATH + "DataTable.json", "peerid", - "didHash", DID); - try { - ArrayList owners = dhtOwnerCheck(tokenID); - if (owners.contains(peerID)) { - ownStatus = true; - } - - } catch (InterruptedException | JSONException | IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return ownStatus; - } - /** * This function converts any integer to its binary form * @@ -1000,6 +1007,7 @@ public static void updateQuorum(JSONArray quorumArray, JSONArray signedQuorumLis dataToSendQuorumUpdate.put("signedquorum", signedQuorumList); dataToSendQuorumUpdate.put("status", status); String populateQuorumUpdate = dataToSendQuorumUpdate.toString(); + FunctionsLogger.debug("Sending 'POST' request to URL : " + urlQuorumUpdate); conQuorumUpdate.setDoOutput(true); DataOutputStream wrQuorumUpdate = new DataOutputStream(conQuorumUpdate.getOutputStream()); @@ -1008,7 +1016,6 @@ public static void updateQuorum(JSONArray quorumArray, JSONArray signedQuorumLis wrQuorumUpdate.close(); int responseCodeQuorumUpdate = conQuorumUpdate.getResponseCode(); - FunctionsLogger.debug("Sending 'POST' request to URL : " + urlQuorumUpdate); FunctionsLogger.debug("Post Data : " + populateQuorumUpdate); FunctionsLogger.debug("Response Code : " + responseCodeQuorumUpdate); @@ -1035,7 +1042,7 @@ public static void updateQuorum(JSONArray quorumArray, JSONArray signedQuorumLis * @return JSONArray of quorum nodes */ - public static JSONArray getQuorum(String betaHash, String gammaHash, String senderDidIpfsHash, + public static JSONArray getQuorum(String senderDidIpfsHash, String receiverDidIpfsHash, int tokenslength) throws IOException, JSONException { JSONArray quorumArray; String urlQuorumPick = ADVISORY_IP + "/getQuorum"; @@ -1049,8 +1056,7 @@ public static JSONArray getQuorum(String betaHash, String gammaHash, String send conQuorumPick.setRequestProperty("Authorization", "null"); JSONObject dataToSendQuorumPick = new JSONObject(); - dataToSendQuorumPick.put("betahash", betaHash); - dataToSendQuorumPick.put("gammahash", gammaHash); + dataToSendQuorumPick.put("sender", senderDidIpfsHash); dataToSendQuorumPick.put("receiver", receiverDidIpfsHash); dataToSendQuorumPick.put("tokencount", tokenslength); @@ -1067,17 +1073,25 @@ public static JSONArray getQuorum(String betaHash, String gammaHash, String send FunctionsLogger.debug("Post Data : " + populateQuorumPick); FunctionsLogger.debug("Response Code : " + responseCodeQuorumPick); - BufferedReader inQuorumPick = new BufferedReader( - new InputStreamReader(conQuorumPick.getInputStream())); - String outputQuorumPick; - StringBuffer responseQuorumPick = new StringBuffer(); - while ((outputQuorumPick = inQuorumPick.readLine()) != null) { - responseQuorumPick.append(outputQuorumPick); + if (responseCodeQuorumPick == 200) { + + BufferedReader inQuorumPick = new BufferedReader( + new InputStreamReader(conQuorumPick.getInputStream())); + String outputQuorumPick; + StringBuffer responseQuorumPick = new StringBuffer(); + while ((outputQuorumPick = inQuorumPick.readLine()) != null) { + responseQuorumPick.append(outputQuorumPick); + } + inQuorumPick.close(); + FunctionsLogger.debug(" responsequorumpick " + responseQuorumPick.toString()); + quorumArray = new JSONArray(responseQuorumPick.toString()); + return quorumArray; + + } else { + quorumArray = new JSONArray(); + quorumArray.put(false); + return quorumArray; } - inQuorumPick.close(); - FunctionsLogger.debug(" responsequorumpick " + responseQuorumPick.toString()); - quorumArray = new JSONArray(responseQuorumPick.toString()); - return quorumArray; } /** @@ -1126,14 +1140,6 @@ public static void mineUpdate(String didHash, int credits) throws IOException, J } - public static String initHash() throws IOException { - String initPath = Functions.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - initPath = initPath.split("\\.jar")[0]; - initPath = initPath + ".jar"; - String initHash = calculateFileHash(initPath, "SHA3-256"); - return initHash; - } - public static int checkHeartBeat(String peerId, String appName) { if (forwardCheck(appName, QUORUM_PORT, peerId)) { @@ -1173,88 +1179,58 @@ public static void syncDataTable(String did, String peerId) { } /** - * This function will release the port in linux based machines if the port is - * already in use + * To Sync DataTable.json, if required */ - public static void releasePorts(int port) { - String processStr; - Process processId; + public static void syncDataTableByDID(String did) { try { - processId = Runtime.getRuntime().exec("lsof -ti :" + port); - long currentPid = ProcessHandle.current().pid(); - BufferedReader br = new BufferedReader( - new InputStreamReader(processId.getInputStream())); - - processId = Runtime.getRuntime().exec("pgrep ipfs"); - BufferedReader ipfsPidBr = new BufferedReader(new InputStreamReader(processId.getInputStream())); - - processStr = br.readLine(); - while (processStr != null - && (String.valueOf(currentPid) != processStr || (ipfsPidBr.readLine() != processStr))) { - FunctionsLogger.debug("Port " + port + " is in using, killing PID " + processStr); - processId = Runtime.getRuntime().exec("kill -9 " + processStr); - + String dataTableData = readFile(DATA_PATH + "DataTable.json"); + boolean isObjectValid = false; + JSONArray dataTable = new JSONArray(dataTableData); + for (int i = 0; i < dataTable.length(); i++) { + JSONObject dataTableObject = dataTable.getJSONObject(i); + if ((did != null && dataTableObject.getString("didHash").equals(did))) { + isObjectValid = true; + break; + } + } + if (!isObjectValid) { + FunctionsLogger.debug("Syncing Datatable.json!"); + APIHandler.networkInfo(); } - processId.waitFor(); - processId.destroy(); - } catch (Exception e) { - FunctionsLogger.error("Exception Occured at releasePort", e); + FunctionsLogger.error("Exception Occured", e); e.printStackTrace(); } } - public static void portStatusWindows(int port) { - String processStr; - Process p; - try { - Runtime rt = Runtime.getRuntime(); - Process proc = rt.exec("cmd /c netstat -ano | findstr " + port); - long currentPid = ProcessHandle.current().pid(); - BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream())); - processStr = stdInput.readLine(); - if (processStr != null && String.valueOf(currentPid) != processStr) { - int index = processStr.lastIndexOf(" "); - String sc = processStr.substring(index, processStr.length()); - // System.out.println("Port "+port+" is locked by PID "+sc+". Kindly close this - // port and retry transcation"); - if (sc != String.valueOf(currentPid)) { - FunctionsLogger.debug("Port " + port + " is locked by PID " + sc); - } else { - FunctionsLogger.debug("Port " + port + " is locked by current jar with PID " + sc); - } + public static void correctToken() throws JSONException { + pathSet(); + String bank = readFile(PAYMENTS_PATH.concat("BNK00.json")); + JSONArray bankArray = new JSONArray(bank); + JSONObject firstToken; + if (bankArray.length() > 1) { + firstToken = bankArray.getJSONObject(0); - } - } catch (Exception e) { - FunctionsLogger.error("Exception occured at portStatusWindows", e); - e.printStackTrace(); + bankArray.remove(0); + bankArray.put(firstToken); + + writeToFile(PAYMENTS_PATH.concat("BNK00.json"), bankArray.toString(), false); } } - public static void removeToken() throws JSONException { - String bnkFile = readFile(PAYMENTS_PATH.concat("BNK00.json")); - JSONArray bnkArray = new JSONArray(bnkFile); - JSONObject removeToken = bnkArray.getJSONObject(0); - bnkArray.remove(0); - writeToFile(PAYMENTS_PATH.concat("BNK00.json"), bnkArray.toString(), false); + public static void correctPartToken() throws JSONException { + pathSet(); + String bank = readFile(PAYMENTS_PATH.concat("PartsToken.json")); + JSONArray bankArray = new JSONArray(bank); + JSONObject firstToken; + if (bankArray.length() > 1) { + firstToken = bankArray.getJSONObject(0); - File doubleSpentFile = new File(PAYMENTS_PATH.concat("DoubleSpent.json")); - if (!doubleSpentFile.exists()) { - try { - doubleSpentFile.createNewFile(); - } catch (IOException e) { - FunctionsLogger.debug("File couldn't be created"); - } - JSONArray removeArray = new JSONArray(); - removeArray.put(removeToken); - writeToFile(PAYMENTS_PATH.concat("DoubleSpent.json"), removeArray.toString(), false); - } else { - String removeFile = readFile(PAYMENTS_PATH.concat("DoubleSpent.json")); - JSONArray removeArray = new JSONArray(removeFile); - removeArray.put(removeToken); - writeToFile(PAYMENTS_PATH.concat("DoubleSpent.json"), removeArray.toString(), false); - } + bankArray.remove(0); + bankArray.put(firstToken); + writeToFile(PAYMENTS_PATH.concat("PartsToken.json"), bankArray.toString(), false); + } } public static void tokenBank() throws JSONException { @@ -1472,6 +1448,48 @@ public static Double getBalance() throws JSONException { return balance; } + public static String initHash() { + String version = ""; + try { + URL url = new URL("http://localhost:1898/getVersion"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + conn.setRequestProperty("Accept", "application/json"); + if (conn.getResponseCode() != 200) { + throw new RuntimeException("Failed : HTTP error code : " + + conn.getResponseCode()); + } + BufferedReader br = new BufferedReader(new InputStreamReader( + (conn.getInputStream()))); + String output; + while ((output = br.readLine()) != null) { + version = output; + } + conn.disconnect(); + FunctionsLogger.debug("initHash version is " + version); + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return version; + } + + /* + * public static String initHash() throws IOException { + * String initPath = + * Functions.class.getProtectionDomain().getCodeSource().getLocation().getPath() + * ; + * initPath = initPath.split("\\.jar")[0]; + * initPath = initPath.split("file:", 2)[1]; + * String jarName[] = initPath.split("\\/"); + * initPath = jarName[jarName.length-1]; + * initPath = initPath + ".jar"; + * String hash = calculateFileHash(initPath, "SHA3-256"); + * return hash; + * } + */ + public static Double partTokenBalance(String tokenHash) throws JSONException { pathSet(); @@ -1551,4 +1569,623 @@ public static void backgroundChecks() { } + public static String sanityMessage; + + public static boolean sanityCheck(String userType, String peerid, IPFS ipfs, int port) + throws IOException, JSONException { + FunctionsLogger.info("Entering " + userType + " SanityCheck"); + boolean sanityCheckErrorFlag = true; + if (sanityCheckErrorFlag && checkIPFSStatus(peerid, ipfs)) { + FunctionsLogger.debug(userType + " IPFS is working in " + peerid); + FunctionsLogger.debug(userType + " IPFS check true"); + } else { + sanityCheckErrorFlag = false; + FunctionsLogger.debug(userType + " IPFS is not working in " + peerid); + FunctionsLogger.debug(userType + " IPFS check false"); + sanityMessage = userType + " IPFS is not working in " + peerid; + } + + if (sanityCheckErrorFlag) { + if (bootstrapConnect(peerid, ipfs)) { + FunctionsLogger.debug("Bootstrap connected for " + userType + " : " + peerid); + FunctionsLogger.debug("Bootstrap check true"); + } else { + sanityCheckErrorFlag = false; + FunctionsLogger.debug("Bootstrap connection unsuccessful for " + userType + " : " + peerid); + FunctionsLogger.debug("Bootstrap check false"); + sanityMessage = "Bootstrap connection unsuccessful for " + userType + " : " + peerid; + } + } + + if (sanityCheckErrorFlag) { + if (ping(peerid, port)) { + FunctionsLogger.debug(userType + " is running the latest Jar :" + peerid); + FunctionsLogger.debug("Latest Jar check true"); + } else { + sanityCheckErrorFlag = false; + FunctionsLogger.debug(userType + " is not running the latest Jar :" + peerid); + FunctionsLogger.debug("Latest Jar check false"); + sanityMessage = userType + " is not running the latest Jar. PID: " + peerid; + } + } + + if (sanityCheckErrorFlag) { + if (portCheckAndKill(port)) { + FunctionsLogger.debug("Ports are available for transcations in " + peerid); + FunctionsLogger.debug("Ports check true"); + } else { + sanityCheckErrorFlag = false; + FunctionsLogger.debug("Ports are not available for " + peerid); + FunctionsLogger.debug("Ports check false"); + sanityMessage = "Ports are not available for " + peerid; + } + } + + return sanityCheckErrorFlag; + } + + public static boolean checkIPFSStatus(String peerid, IPFS ipfs) { + FunctionsLogger.info("Entering checkIPFSStatus"); + boolean swarmConnectedStatus = false; + try { + MultiAddress multiAddress = new MultiAddress("/ipfs/" + peerid); + FunctionsLogger.info("MultiAdrress concated " + multiAddress + "|||"); + boolean output = swarmConnectP2P(peerid, ipfs); + + if (output) { + swarmConnectedStatus = true; + FunctionsLogger.debug("Swarm is already connected"); + } else { + swarmConnectedStatus = false; + FunctionsLogger.debug("Swarm is not connected"); + } + } catch (Exception e) { + FunctionsLogger.error("Check Swarm Connect is failed", e); + + } + FunctionsLogger.info("checkIPFSStatus return value is " + swarmConnectedStatus); + return swarmConnectedStatus; + } + + public static boolean ping(String peerid, int port) throws IOException, JSONException { + JSONObject pingCheck = PingCheck.Ping(peerid, port); + FunctionsLogger.info("Ping Check Response " + pingCheck); + if (pingCheck.getString("status").contains("Failed")) { + return false; + } else + return true; + + } + + // public static String getPing(int port) { + // try { + // + // String didContent = readFile(DATA_PATH + "DID.json"); + // JSONArray didArray = new JSONArray(didContent); + // String myPeerID = didArray.getJSONObject(0).getString("peerid"); + // + // listen(myPeerID.concat("Ping"), port); + // ServerSocket ss = new ServerSocket(port); + // FunctionsLogger.info("Get Ping Listening on port " + port + " appname " + + // myPeerID.concat("Ping")); + // Socket socket = ss.accept(); + // BufferedReader input = new BufferedReader(new + // InputStreamReader(socket.getInputStream())); + // PrintStream output = new PrintStream(socket.getOutputStream()); + // FunctionsLogger.info("getPing- waiting response from server"); + // String peerID = input.readLine(); + // if (peerID != null && peerID.contains("Qm")) { + // FunctionsLogger.info("getPing - Received message from server"); + // output.println("Ping received"); + // FunctionsLogger.debug("Ping received from sender"); + // + // output.close(); + // input.close(); + // socket.close(); + // ss.close(); + // executeIPFSCommands(" ipfs p2p close -t /p2p/" + peerID); + // FunctionsLogger.info("If - Closing Sockets"); + // return "Ping received from sender and Pong sent"; + // } + // else{ + // output.close(); + // input.close(); + // socket.close(); + // ss.close(); + // FunctionsLogger.info("Else - Closing Sockets"); + // return "Ping received from sender but not PeerID"; + // } + // + // } catch (Exception e) { + // FunctionsLogger.error("Error in client side communication", e); + // return "Error in client side communication"; + // } + // } + + public static boolean bootstrapConnect(String peerid, IPFS ipfs) { + FunctionsLogger.info("bootstrapConnect- entering function"); + String bootNode; + boolean bootstrapConnected = false; + + MultiAddress multiAddress = new MultiAddress("/ipfs/" + peerid); + FunctionsLogger.info("bootstrapConnect- multiaddress is " + multiAddress.toString()); + + String output = swarmConnectProcess(multiAddress); + try { + for (int i = 0; i < BOOTSTRAPS.length(); i++) { + FunctionsLogger.info("bootstrapConnect- Bootstrap length is " + BOOTSTRAPS.length()); + + if (!bootstrapConnected) { + FunctionsLogger.info("bootstrapConnect- Connecting to bootstrp " + i); + bootNode = String.valueOf(BOOTSTRAPS.get(i)); + bootNode = bootNode.substring(bootNode.length() - 46); + FunctionsLogger.info("bootstrapConnect- trying to connect with " + bootNode); + + multiAddress = new MultiAddress("/ipfs/" + bootNode); + output = swarmConnectProcess(multiAddress); + FunctionsLogger.info("bootstrapConnect- connection status to " + bootNode + " is " + output); + if (output.contains("success")) { + FunctionsLogger.info("bootstrapConnect- trying to swarm connect"); + multiAddress = new MultiAddress("/ipfs/" + bootNode + "/p2p-circuit/ipfs/" + peerid); + output = swarmConnectProcess(multiAddress); + FunctionsLogger.info("bootstrapConnect- Swarmconnect status is " + output); + if (!output.contains("success")) { + IPFSNetworkLogger.debug("swarm attempt failed with " + peerid); + } else { + IPFSNetworkLogger.debug("swarm Connected : " + peerid); + bootstrapConnected = true; + } + } else { + IPFSNetworkLogger.debug("bootstrap connection failed! " + bootNode); + } + + } + } + + } catch (Exception e) { + FunctionsLogger.error("Error occured during IPFS Swarm connect with bootstrap", e); + + } + + if (bootstrapConnected) { + return true; + } else { + return false; + } + + } + + public static boolean portCheckAndKill(int port) { + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + boolean portStatus = false; + long pid = ProcessHandle.current().pid(); + FunctionsLogger.info("Current OS is " + getOsName()); + try { + if (!getOsName().toLowerCase().contains("windows")) { + portStatus = releasePorts(port); + } else { + portStatus = portStatusWindows(port); + } + } catch (Exception e) { + FunctionsLogger.error("Error occured during port checking ", e); + } + return portStatus; + + } + + /** + * This function will release the port in linux based machines if the port is + * already in use + */ + public static boolean releasePorts(int port) { + FunctionsLogger.info("releasePorts- "); + boolean releasedPort = false; + String processStr; + Process processId; + try { + processId = Runtime.getRuntime().exec("lsof -ti :" + port); + long currentPid = ProcessHandle.current().pid(); + BufferedReader br = new BufferedReader( + new InputStreamReader(processId.getInputStream())); + FunctionsLogger.info("releasePorts- process " + br.readLine() + " is occupied in " + port); + processId = Runtime.getRuntime().exec("pgrep ipfs"); + BufferedReader ipfsPidBr = new BufferedReader(new InputStreamReader(processId.getInputStream())); + + processStr = br.readLine(); + FunctionsLogger.info("releasePorts- Process string is " + processStr); + if (processStr != null) { + FunctionsLogger.info("releasePorts- Processstr is not null"); + if (String.valueOf(currentPid) != processStr && ipfsPidBr.readLine() != processStr) { + FunctionsLogger.info("releasePorts- jar is running on " + currentPid + " and IPFS is occupied in " + + ipfsPidBr.readLine()); + FunctionsLogger.debug("Port " + port + " is in using, killing PID " + processStr); + processId = Runtime.getRuntime().exec("kill -9 " + processStr); + FunctionsLogger.info("releasePorts- killing " + processStr); + + } + } + releasedPort = true; + FunctionsLogger.info("releasePorts- status is " + releasedPort); + processId.waitFor(); + FunctionsLogger.info("releasePorts- Waitng for process"); + processId.destroy(); + FunctionsLogger.info("releasePorts- destorying process after waiting"); + } catch (Exception e) { + FunctionsLogger.error("Exception Occured at releasePort", e); + e.printStackTrace(); + } + return releasedPort; + } + + public static boolean portStatusWindows(int port) { + FunctionsLogger.info("Starting portStatusWindows"); + boolean releasedPort = false; + String portProcessStr; + Process p; + ArrayList pidTree = new ArrayList(); + ArrayList portPidTree = new ArrayList(); + try { + Runtime rt = Runtime.getRuntime(); + Process getJarPid = rt.exec("cmd /c netstat -ano | findstr 1898"); + BufferedReader getJarPidBR = new BufferedReader(new InputStreamReader(getJarPid.getInputStream())); + String getJarPidline; + while ((getJarPidline = getJarPidBR.readLine()) != null) { + String[] getJarPidTree = getJarPidline.split("\\s+"); + int temp = Integer.parseInt(getJarPidTree[getJarPidTree.length - 1]); + pidTree.add(temp); + } + + FunctionsLogger.info("PIDs occupied by Rubix.jar are " + pidTree); + + Set pidSet = new LinkedHashSet(pidTree); + FunctionsLogger.info("Pid occupied by port 1898 is pidSet" + pidSet); + Process getPortPid = rt.exec("cmd /c netstat -ano | findstr " + port); + BufferedReader getPortPidBr = new BufferedReader(new InputStreamReader(getPortPid.getInputStream())); + String getPortPidLine; + while ((getPortPidLine = getPortPidBr.readLine()) != null) { + String[] getPortPidTree = getPortPidLine.split("\\s+"); + int temp = Integer.parseInt(getPortPidTree[getPortPidTree.length - 1]); + portPidTree.add(temp); + } + + Set pidToKill = new LinkedHashSet(portPidTree); + FunctionsLogger.info("Pid used by port " + port + "is " + pidToKill); + pidToKill.removeAll(pidSet); + pidToKill.remove(0); + FunctionsLogger.info("Pid using port " + port + " but not in 1898" + pidToKill); + if (pidToKill.size() > 0) { + System.out.println("Port " + port + " is occupied by PIDs" + pidToKill); + } else { + releasedPort = true; + } + + } catch (Exception e) { + FunctionsLogger.error("Exception occured at portStatusWindows", e); + } + return releasedPort; + + } + + public static void ownerIdentity(JSONArray tokens, String receiverDidIpfsHash) { + Functions.pathSet(); + + try { + for (int i = 0; i < tokens.length(); i++) { + + String tokenHash = tokens.getString(i); + String hashString = tokenHash.concat(receiverDidIpfsHash); + String hashForPositions = calculateHash(hashString, "SHA3-256"); + BufferedImage pvt = ImageIO.read(new File(DATA_PATH.concat(receiverDidIpfsHash).concat("/PrivateShare.png"))); + String firstPrivate = PropImage.img2bin(pvt); + int[] privateIntegerArray1 = strToIntArray(firstPrivate); + String privateBinary = Functions.intArrayToStr(privateIntegerArray1); + String positions = ""; + for (int j = 0; j < privateIntegerArray1.length; j += 49152) { + positions += privateBinary.charAt(j); + } + String ownerIdentity = hashForPositions.concat(positions); + String ownerIdentityHash = calculateHash(ownerIdentity, "SHA3-256"); + File chainFile = new File(TOKENCHAIN_PATH.concat(tokenHash).concat(".json")); + if (chainFile.exists()) { + String tokenChainFile = readFile(TOKENCHAIN_PATH.concat(tokenHash).concat(".json")); + JSONArray tokenChainArray = new JSONArray(tokenChainFile); + JSONObject tokenChainObject = tokenChainArray.getJSONObject(tokenChainArray.length() - 1); + tokenChainObject.put("owner", ownerIdentityHash); + tokenChainArray.remove(tokenChainArray.length() - 1); + tokenChainArray.put(tokenChainObject); + writeToFile(TOKENCHAIN_PATH.concat(tokenHash).concat(".json"), tokenChainArray.toString(), false); + + } else { + File partChainFile = new File(TOKENCHAIN_PATH.concat("PARTS/").concat(tokenHash).concat(".json")); + if (partChainFile.exists()) { + String tokenChainFile = readFile(TOKENCHAIN_PATH.concat("PARTS/").concat(tokenHash).concat(".json")); + JSONArray tokenChainArray = new JSONArray(tokenChainFile); + JSONObject tokenChainObject = tokenChainArray.getJSONObject(tokenChainArray.length() - 1); + tokenChainObject.put("owner", ownerIdentityHash); + tokenChainArray.remove(tokenChainArray.length() - 1); + tokenChainArray.put(tokenChainObject); + writeToFile(TOKENCHAIN_PATH.concat("PARTS/").concat(tokenHash).concat(".json"), tokenChainArray.toString(), false); + + } else { + FunctionsLogger.info("Token chain file not found for token " + tokenHash); + } + + } + + + } + } catch (Exception e) { + FunctionsLogger.error("Exception occured at ownerIdentity", e); + } + + + + } + + public static int multiplePinCheck(String senderDidIpfsHash,JSONObject tokenObject, IPFS ipfs) throws JSONException, InterruptedException { + int statusCode = 200; + FunctionsLogger.debug("Input tokenObject is "+tokenObject.toString()); + JSONObject TokenDetails = tokenObject.getJSONObject("tokenDetails"); + JSONArray wholeTokens = TokenDetails.getJSONArray("whole-tokens"); + JSONArray wholeTokenChains = TokenDetails.getJSONArray("whole-tokenChains"); + + JSONArray partTokens = TokenDetails.getJSONArray("part-tokens"); + JSONObject partTokenChains = TokenDetails.getJSONObject("part-tokenChains"); + JSONArray partTokenChainsHash = TokenDetails.getJSONArray("hashSender"); + + JSONArray previousSendersArray = tokenObject.getJSONArray("previousSender"); + JSONArray positionsArray = tokenObject.getJSONArray("positions"); + + Double amount = tokenObject.getDouble("amount"); + JSONObject amountLedger = tokenObject.getJSONObject("amountLedger"); + FunctionsLogger.debug("Amount Ledger: " + amountLedger); + int intPart = wholeTokens.length(); + // ? multiple pin check starts + Double decimalPart = formatAmount(amount - intPart); + JSONArray doubleSpentToken = new JSONArray(); + boolean tokenOwners = true; + ArrayList pinOwnersArray = new ArrayList(); + ArrayList previousSender = new ArrayList(); + JSONArray ownersReceived = new JSONArray(); + + ArrayList ownersArray = new ArrayList(); + for (int i = 0; i < wholeTokens.length(); ++i) { + try { + FunctionsLogger.debug("Checking owners for " + wholeTokens.getString(i) + + " Please wait..."); + pinOwnersArray = IPFSNetwork.dhtOwnerCheck(wholeTokens.getString(i)); + + if (pinOwnersArray.size() > 2) { + + for (int j = 0; j < previousSendersArray.length(); j++) { + if (previousSendersArray.getJSONObject(j).getString("token") + .equals(wholeTokens.getString(i))) + ownersReceived = previousSendersArray.getJSONObject(j).getJSONArray("sender"); + } + + for (int j = 0; j < ownersReceived.length(); j++) { + previousSender.add(ownersReceived.getString(j)); + } + FunctionsLogger.debug("Previous Owners: " + previousSender); + + for (int j = 0; j < pinOwnersArray.size(); j++) { + if (!previousSender.contains(pinOwnersArray.get(j).toString())) + tokenOwners = false; + } + } + } catch (IOException e) { + + FunctionsLogger.debug("Ipfs dht find did not execute"); + } + } + if (!tokenOwners) { + JSONArray owners = new JSONArray(); + for (int i = 0; i < pinOwnersArray.size(); i++) + owners.put(pinOwnersArray.get(i).toString()); + FunctionsLogger.debug("Multiple Owners for " + doubleSpentToken); + FunctionsLogger.debug("Owners: " + owners); + statusCode = 420; + + return statusCode; + } + + return statusCode; + } + + public static boolean generateMultiLoopWithHashMap(String path) throws InterruptedException { + FunctionsLogger.debug("path is " + path); + FunctionsLogger.debug("path with file" + path+"/DH00.json"); + File dataHashPath = new File(path); + if (!dataHashPath.exists()) + dataHashPath.mkdir(); + boolean status = false; + FunctionsLogger.debug("Main thread started at" + java.time.LocalTime.now()); + + long tStart = System.currentTimeMillis(); + Thread generateHashMapThread1 = new Thread(() -> { + FunctionsLogger.debug("T1 started at" + java.time.LocalTime.now()); + HashMap tokenHashMap = new HashMap(); + JSONObject tokenHashTableJSON = new JSONObject(tokenHashMap); + + File tokenHashTable = new File(path+"/DH00.json"); + long start = System.currentTimeMillis(); + for (int i = 1; i <= 1250000; i++) { + tokenHashMap.put(calculateHash(String.valueOf(i), "SHA-256"), i); + } + tokenHashTableJSON = new JSONObject(tokenHashMap); + writeToFile(tokenHashTable.toString(), tokenHashTableJSON.toString(), false); + FunctionsLogger.debug("T1 ended at" + java.time.LocalTime.now()); + + tokenHashMap.clear(); + long end = System.currentTimeMillis(); + FunctionsLogger.debug("Write to file done in t1 : " + + (end - start) + "ms"); + }); + Thread generateHashMapThread2 = new Thread(() -> { + System.out.println("T2 started at" + java.time.LocalTime.now()); + + HashMap tokenHashMap = new HashMap(); + JSONObject tokenHashTableJSON = new JSONObject(tokenHashMap); + long start = System.currentTimeMillis(); + File tokenHashTable = new File(path+"/DH01.json"); + + for (int i = 1250001; i < 2500000; i++) { + tokenHashMap.put(calculateHash(String.valueOf(i), "SHA-256"), i); + } + tokenHashTableJSON = new JSONObject(tokenHashMap); + writeToFile(tokenHashTable.toString(), tokenHashTableJSON.toString(), false); + FunctionsLogger.debug("T2 ended at" + java.time.LocalTime.now()); + + tokenHashMap.clear(); + long end = System.currentTimeMillis(); + FunctionsLogger.debug("Write to file done in t2 : " + + (end - start) + "ms"); + }); + + Thread generateHashMapThread3 = new Thread(() -> { + System.out.println("T3 started at" + java.time.LocalTime.now()); + + HashMap tokenHashMap = new HashMap(); + JSONObject tokenHashTableJSON = new JSONObject(tokenHashMap); + long start = System.currentTimeMillis(); + File tokenHashTable = new File(path+"/DH02.json"); + for (int i = 2500001; i <= 3750000; i++) { + tokenHashMap.put(calculateHash(String.valueOf(i), "SHA-256"), i); + } + tokenHashTableJSON = new JSONObject(tokenHashMap); + writeToFile(tokenHashTable.toString(), tokenHashTableJSON.toString(), false); + FunctionsLogger.debug("T3 ended at" + java.time.LocalTime.now()); + + tokenHashMap.clear(); + + long tEnd = System.currentTimeMillis(); + System.out.println("Write to file done in t3 : " + + (tEnd - start) + "ms"); + }); + + Thread generateHashMapThread4 = new Thread(() -> { + System.out.println("T4 started at" + java.time.LocalTime.now()); + + HashMap tokenHashMap = new HashMap(); + JSONObject tokenHashTableJSON = new JSONObject(tokenHashMap); + long start = System.currentTimeMillis(); + File tokenHashTable = new File(path+"/DH03.json"); + for (int i = 3750001; i <= 5000000; i++) { + tokenHashMap.put(calculateHash(String.valueOf(i), "SHA-256"), i); + } + tokenHashTableJSON = new JSONObject(tokenHashMap); + writeToFile(tokenHashTable.toString(), tokenHashTableJSON.toString(), false); + FunctionsLogger.debug("T4 ended at" + java.time.LocalTime.now()); + + tokenHashMap.clear(); + long end = System.currentTimeMillis(); + FunctionsLogger.debug("Write to file done in t4 : " + + (end - start) + "ms"); + }); + + generateHashMapThread1.start(); + generateHashMapThread2.start(); + generateHashMapThread3.start(); + generateHashMapThread4.start(); + + + + FunctionsLogger.debug("Main ended at" + java.time.LocalTime.now()); + + long end = System.currentTimeMillis(); + FunctionsLogger.debug("Main thread" + + (end - tStart) + "ms"); + + generateHashMapThread1.join(); + generateHashMapThread2.join(); + generateHashMapThread3.join(); + generateHashMapThread4.join(); + + File filepath = new File(path); + if ((filepath.length() == 4)) { + FunctionsLogger.debug("DataHashTable size is"+filepath.length()); + status = true; + }else{ + status = false; + } + + return status; + } + + + public static int readTokenHashTable(String path,String tokenContent) throws JSONException { + File filePath = new File(path); + FunctionsLogger.debug("File path to add is "+path); + File[] tokenHashTable = filePath.listFiles(); + Arrays.sort(tokenHashTable); + int tokenNumber = -1; + + for (File tokenHashTableFile : tokenHashTable) { + FunctionsLogger.debug(tokenHashTableFile.getName()); + JSONObject tokenHashTableJSON = new JSONObject(readFile(tokenHashTableFile.toString())); + if (tokenHashTableJSON.has(tokenContent)) { + tokenNumber = tokenHashTableJSON.getInt(tokenContent); + return tokenNumber; + } + + } + return tokenNumber; + + } + + public static HashMap checkTokenHash(HashMap tokenDetailMap, int tokenLimit) throws InterruptedException { + HashMap tokenHashWithNumber = new HashMap<>(); + + int tokenNumber = -1; + try { + long start = System.currentTimeMillis(); + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + + int flag = -1; + for(int i=1;i<=tokenLimit;i++) { + String tokenHashStr = calculateSHA256Hash(digest, String.valueOf(i)); + for(String tokenHash : tokenDetailMap.keySet()) { + if(tokenHash.equals(tokenHashStr)) { + tokenNumber = i; + flag++; + tokenHashWithNumber.put(tokenHash, i); + FunctionsLogger.debug("TokenHash is "+ tokenHash + " and token number is "+i); + } + + } + } + + FunctionsLogger.debug("final tokenHashMap is "+tokenHashWithNumber.toString()); + + + }catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + }catch (Exception e) { + e.printStackTrace(); + } + + return tokenHashWithNumber; + } + + + /** + * This method calculates different types of hashes as mentioned in the passed + * parameters for the mentioned message + * + * @param message Input string to be hashed + * @param + * @return (String) hash + */ + + private static String calculateSHA256Hash(MessageDigest digest, String message) { + byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8); + byte[] c = new byte[messageBytes.length]; + System.arraycopy(messageBytes, 0, c, 0, messageBytes.length); + final byte[] hashBytes = digest.digest(messageBytes); + return bytesToHex(hashBytes); + } + + + + } diff --git a/src/com/rubix/Resources/IPFSNetwork.java b/src/com/rubix/Resources/IPFSNetwork.java index 2921d551..9892b039 100644 --- a/src/com/rubix/Resources/IPFSNetwork.java +++ b/src/com/rubix/Resources/IPFSNetwork.java @@ -1,22 +1,35 @@ package com.rubix.Resources; -import io.ipfs.api.IPFS; -import io.ipfs.api.MerkleNode; -import io.ipfs.api.NamedStreamable; -import io.ipfs.multiaddr.MultiAddress; -import io.ipfs.multihash.Multihash; -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; -import org.json.JSONException; +import static com.rubix.Constants.IPFSConstants.bootstrap; +import static com.rubix.Constants.IPFSConstants.daemon; +import static com.rubix.Constants.IPFSConstants.forward; +import static com.rubix.Constants.IPFSConstants.listen; +import static com.rubix.Constants.IPFSConstants.p2p; +import static com.rubix.Constants.IPFSConstants.shutdown; +import static com.rubix.Resources.Functions.BOOTSTRAPS; +import static com.rubix.Resources.Functions.LOGGER_PATH; +import static com.rubix.Resources.Functions.getOsName; -import javax.imageio.ImageIO; import java.awt.image.BufferedImage; -import java.io.*; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; -import static com.rubix.Constants.IPFSConstants.*; -import static com.rubix.Resources.Functions.*; +import javax.imageio.ImageIO; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.json.JSONException; + +import io.ipfs.api.IPFS; +import io.ipfs.api.MerkleNode; +import io.ipfs.api.NamedStreamable; +import io.ipfs.multiaddr.MultiAddress; +import io.ipfs.multihash.Multihash; public class IPFSNetwork { public static int swarmAttempt = 0; @@ -69,105 +82,109 @@ public static String checkSwarmConnect() { return response; } -// public static void swarmConnector(String peerid, IPFS ipfs) throws JSONException { -// PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); -// String bootNode; -// int j; -// -// try { -// if (!checkSwarmConnect().contains(peerid)) { -// Random ran = new Random(); -// -// List bootStrapList = ipfs.bootstrap.list(); -// Collections.shuffle(bootStrapList); -// ran.setSeed(123456); -// int bootstrapSize = bootStrapList.size(); -// -// j = ran.nextInt(bootstrapSize); -// bootNode = String.valueOf(bootStrapList.get(j)); -// bootNode = bootNode.substring(bootNode.length() - 46); -// IPFSNetworkLogger.debug(bootNode); -// while (!checkSwarmConnect().contains(bootNode)) { -// j = (j + 1) % bootstrapSize; -// bootNode = String.valueOf(bootStrapList.get(j)); -// bootNode = bootNode.substring(bootNode.length() - 46); -// IPFSNetworkLogger.debug("trying to connect: " + bootNode); -// } -// MultiAddress multiAddress = new MultiAddress("/p2p/" + bootNode + "/p2p-circuit/p2p/" + peerid); -// String output = swarmConnectProcess(multiAddress); -// if (!output.contains("success")) -// swarmConnect(peerid); -// else -// IPFSNetworkLogger.debug("Connected via bootstrap node: " + bootNode); -// } else { -// IPFSNetworkLogger.debug("Connecting to Receiver directly"); -// -// } -// } catch (IOException e) { -// IPFSNetworkLogger.error("IOException Occurred", e); -// e.printStackTrace(); -// } -// -// } - -// /** -// * This method opens a new direct connection to a peer address. The address -// * format is an IPFS multiaddr. See -// * ipfs -// * swarm connect for more -// * -// * @param peerid is the multiaddr of the node -// */ -// -// public static void swarmConnect(String peerid) throws JSONException { -// PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); -// String bootNode; -// int j; -// -// IPFSNetworkLogger.debug("at swarmconnect " + peerid); -// if (!checkSwarmConnect().contains(peerid)) { -// Random ran = new Random(); -// -//// List bootStrapList = ipfs.bootstrap.list(); -//// Collections.shuffle(bootStrapList); -// ran.setSeed(123456); -// int bootstrapSize = BOOTSTRAPS.length(); -// -// IPFSNetworkLogger.debug("Bootstraps " + BOOTSTRAPS + "size " + bootstrapSize); -// -// j = ran.nextInt(bootstrapSize); -// bootNode = String.valueOf(BOOTSTRAPS.get(j)); -// bootNode = bootNode.substring(bootNode.length() - 46); -// IPFSNetworkLogger.debug("bootnode is " + bootNode); -// IPFSNetworkLogger.debug(bootNode); -// while (!checkSwarmConnect().contains(bootNode)) { -// j = (j + 1) % bootstrapSize; -// bootNode = String.valueOf(BOOTSTRAPS.get(j)); -// bootNode = bootNode.substring(bootNode.length() - 46); -// IPFSNetworkLogger.debug("trying to connect: " + bootNode); -// } -// MultiAddress multiAddress = new MultiAddress("/ipfs/" + bootNode + "/p2p-circuit/ipfs/" + peerid); -// String output = swarmConnectProcess(multiAddress); -// if (!output.contains("success")) { -// if (swarmAttempt < 25) { -// IPFSNetworkLogger.debug("swarm attempt round " + swarmAttempt); -// swarmAttempt++; -// swarmConnect(peerid); -// } else { -// IPFSNetworkLogger.debug("swarm attempt failed"); -// swarmAttempt = 0; -// } -// } else { -// IPFSNetworkLogger.debug("Connected via bootstrap node: " + bootNode); -// swarmAttempt = 0; -// } -// } else { -// IPFSNetworkLogger.debug("Connecting to Receiver directly"); -// swarmAttempt = 0; -// -// } -// -// } + // public static void swarmConnector(String peerid, IPFS ipfs) throws + // JSONException { + // PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + // String bootNode; + // int j; + // + // try { + // if (!checkSwarmConnect().contains(peerid)) { + // Random ran = new Random(); + // + // List bootStrapList = ipfs.bootstrap.list(); + // Collections.shuffle(bootStrapList); + // ran.setSeed(123456); + // int bootstrapSize = bootStrapList.size(); + // + // j = ran.nextInt(bootstrapSize); + // bootNode = String.valueOf(bootStrapList.get(j)); + // bootNode = bootNode.substring(bootNode.length() - 46); + // IPFSNetworkLogger.debug(bootNode); + // while (!checkSwarmConnect().contains(bootNode)) { + // j = (j + 1) % bootstrapSize; + // bootNode = String.valueOf(bootStrapList.get(j)); + // bootNode = bootNode.substring(bootNode.length() - 46); + // IPFSNetworkLogger.debug("trying to connect: " + bootNode); + // } + // MultiAddress multiAddress = new MultiAddress("/p2p/" + bootNode + + // "/p2p-circuit/p2p/" + peerid); + // String output = swarmConnectProcess(multiAddress); + // if (!output.contains("success")) + // swarmConnect(peerid); + // else + // IPFSNetworkLogger.debug("Connected via bootstrap node: " + bootNode); + // } else { + // IPFSNetworkLogger.debug("Connecting to Receiver directly"); + // + // } + // } catch (IOException e) { + // IPFSNetworkLogger.error("IOException Occurred", e); + // e.printStackTrace(); + // } + // + // } + + // /** + // * This method opens a new direct connection to a peer address. The address + // * format is an IPFS multiaddr. See + // * ipfs + // * swarm connect for more + // * + // * @param peerid is the multiaddr of the node + // */ + // + // public static void swarmConnect(String peerid) throws JSONException { + // PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + // String bootNode; + // int j; + // + // IPFSNetworkLogger.debug("at swarmconnect " + peerid); + // if (!checkSwarmConnect().contains(peerid)) { + // Random ran = new Random(); + // + //// List bootStrapList = ipfs.bootstrap.list(); + //// Collections.shuffle(bootStrapList); + // ran.setSeed(123456); + // int bootstrapSize = BOOTSTRAPS.length(); + // + // IPFSNetworkLogger.debug("Bootstraps " + BOOTSTRAPS + "size " + + // bootstrapSize); + // + // j = ran.nextInt(bootstrapSize); + // bootNode = String.valueOf(BOOTSTRAPS.get(j)); + // bootNode = bootNode.substring(bootNode.length() - 46); + // IPFSNetworkLogger.debug("bootnode is " + bootNode); + // IPFSNetworkLogger.debug(bootNode); + // while (!checkSwarmConnect().contains(bootNode)) { + // j = (j + 1) % bootstrapSize; + // bootNode = String.valueOf(BOOTSTRAPS.get(j)); + // bootNode = bootNode.substring(bootNode.length() - 46); + // IPFSNetworkLogger.debug("trying to connect: " + bootNode); + // } + // MultiAddress multiAddress = new MultiAddress("/ipfs/" + bootNode + + // "/p2p-circuit/ipfs/" + peerid); + // String output = swarmConnectProcess(multiAddress); + // if (!output.contains("success")) { + // if (swarmAttempt < 25) { + // IPFSNetworkLogger.debug("swarm attempt round " + swarmAttempt); + // swarmAttempt++; + // swarmConnect(peerid); + // } else { + // IPFSNetworkLogger.debug("swarm attempt failed"); + // swarmAttempt = 0; + // } + // } else { + // IPFSNetworkLogger.debug("Connected via bootstrap node: " + bootNode); + // swarmAttempt = 0; + // } + // } else { + // IPFSNetworkLogger.debug("Connecting to Receiver directly"); + // swarmAttempt = 0; + // + // } + // + // } /** * This function connects the peer node through the private swarm @@ -365,7 +382,6 @@ public static ArrayList dhtOwnerCheck(String objectHash) throws InterruptedExcep commands[2] = "ipfs dht findprovs " + objectHash; } - ProcessBuilder p = new ProcessBuilder(commands); Process process = p.start(); @@ -378,7 +394,6 @@ public static ArrayList dhtOwnerCheck(String objectHash) throws InterruptedExcep array.add(line); process.waitFor(); - return array; } @@ -452,7 +467,8 @@ public static String executeIPFSCommandsResponse(String command) { } if (command.contains(listen) || command.contains(forward) || command.contains("swarm") - || command.contains(p2p) || command.contains(shutdown) || command.contains(bootstrap) || command.contains("findprovs")) { + || command.contains(p2p) || command.contains(shutdown) || command.contains(bootstrap) + || command.contains("findprovs")) { p = new ProcessBuilder(commands); process = p.start(); @@ -544,7 +560,7 @@ public static void executeIPFSCommands(String command) { } } - public static void swarmConnectP2P(String peerid, IPFS ipfs) throws JSONException { + public static boolean swarmConnectP2P(String peerid, IPFS ipfs) throws JSONException { PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); String bootNode; boolean swarmConnected = false; @@ -560,26 +576,31 @@ public static void swarmConnectP2P(String peerid, IPFS ipfs) throws JSONExceptio if (!swarmConnected) { bootNode = String.valueOf(BOOTSTRAPS.get(i)); bootNode = bootNode.substring(bootNode.length() - 46); - + multiAddress = new MultiAddress("/ipfs/" + bootNode); output = swarmConnectProcess(multiAddress); - + if (output.contains("success")) { - multiAddress = new MultiAddress("/ipfs/" + bootNode + "/p2p-circuit/ipfs/" + peerid); - output = swarmConnectProcess(multiAddress); - if (!output.contains("success")) { - IPFSNetworkLogger.debug("swarm attempt failed with " + peerid); - } else { - IPFSNetworkLogger.debug("swarm Connected : " + peerid); - swarmConnected = true; - } + multiAddress = new MultiAddress("/ipfs/" + bootNode + "/p2p-circuit/ipfs/" + peerid); + output = swarmConnectProcess(multiAddress); + if (!output.contains("success")) { + IPFSNetworkLogger.debug("swarm attempt failed with " + peerid); + swarmConnected = false; + } else { + IPFSNetworkLogger.debug("swarm Connected : " + peerid); + swarmConnected = true; + } } else { - IPFSNetworkLogger.debug("bootstrap connection failed! " + bootNode); - } + IPFSNetworkLogger.debug("bootstrap connection failed! " + bootNode); + swarmConnected = false; + } } } + } else { + swarmConnected = true; } + return swarmConnected; } diff --git a/src/com/rubix/TokenTransfer/TokenReceiver.java b/src/com/rubix/TokenTransfer/TokenReceiver.java index 3707abf2..4c3bf08b 100644 --- a/src/com/rubix/TokenTransfer/TokenReceiver.java +++ b/src/com/rubix/TokenTransfer/TokenReceiver.java @@ -1,33 +1,7 @@ package com.rubix.TokenTransfer; -import static com.rubix.Resources.Functions.DATA_PATH; -import static com.rubix.Resources.Functions.FunctionsLogger; -import static com.rubix.Resources.Functions.IPFS_PORT; -import static com.rubix.Resources.Functions.LOGGER_PATH; -import static com.rubix.Resources.Functions.PAYMENTS_PATH; -import static com.rubix.Resources.Functions.RECEIVER_PORT; -import static com.rubix.Resources.Functions.TOKENCHAIN_PATH; -import static com.rubix.Resources.Functions.TOKENS_PATH; -import static com.rubix.Resources.Functions.WALLET_DATA_PATH; -import static com.rubix.Resources.Functions.calculateHash; -import static com.rubix.Resources.Functions.deleteFile; -import static com.rubix.Resources.Functions.formatAmount; -import static com.rubix.Resources.Functions.getCurrentUtcTime; -import static com.rubix.Resources.Functions.getPeerID; -import static com.rubix.Resources.Functions.getValues; -import static com.rubix.Resources.Functions.nodeData; -import static com.rubix.Resources.Functions.pathSet; -import static com.rubix.Resources.Functions.readFile; -import static com.rubix.Resources.Functions.syncDataTable; -import static com.rubix.Resources.Functions.updateJSON; -import static com.rubix.Resources.Functions.writeToFile; -import static com.rubix.Resources.IPFSNetwork.add; -import static com.rubix.Resources.IPFSNetwork.executeIPFSCommands; -import static com.rubix.Resources.IPFSNetwork.get; -import static com.rubix.Resources.IPFSNetwork.listen; -import static com.rubix.Resources.IPFSNetwork.pin; -import static com.rubix.Resources.IPFSNetwork.repo; -import static com.rubix.Resources.IPFSNetwork.swarmConnectP2P; +import static com.rubix.Resources.Functions.*; +import static com.rubix.Resources.IPFSNetwork.*; import java.awt.image.BufferedImage; import java.io.BufferedReader; @@ -39,15 +13,23 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; +import java.util.Random; import javax.imageio.ImageIO; import com.rubix.AuthenticateNode.Authenticate; import com.rubix.AuthenticateNode.PropImage; +import com.rubix.Ping.VerifyStakedToken; import com.rubix.Resources.Functions; import com.rubix.Resources.IPFSNetwork; +import com.rubix.Constants.MiningConstants.*; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; @@ -55,744 +37,1176 @@ import org.json.JSONException; import org.json.JSONObject; +import com.rubix.Constants.*; + import io.ipfs.api.IPFS; public class TokenReceiver { - public static Logger TokenReceiverLogger = Logger.getLogger(TokenReceiver.class); - - private static final JSONObject APIResponse = new JSONObject(); - private static IPFS ipfs = new IPFS("/ip4/127.0.0.1/tcp/" + IPFS_PORT); - private static String SenWalletBin; - - /** - * Receiver Node: To receive a valid token from an authentic sender - * - * @return Transaction Details (JSONObject) - * @throws IOException handles IO Exceptions - * @throws JSONException handles JSON Exceptions - */ - public static String receive() { - pathSet(); - ServerSocket ss = null; - Socket sk = null; - String senderPeerID = null; - - try { - repo(ipfs); - String PART_TOKEN_CHAIN_PATH = TOKENCHAIN_PATH.concat("PARTS/"); - String PART_TOKEN_PATH = TOKENS_PATH.concat("PARTS/"); - File partFolder = new File(PART_TOKEN_PATH); - if (!partFolder.exists()) - partFolder.mkdir(); - partFolder = new File(PART_TOKEN_CHAIN_PATH); - if (!partFolder.exists()) - partFolder.mkdir(); - File partTokensFile = new File(PAYMENTS_PATH.concat("PartsToken.json")); - if (!partTokensFile.exists()) { - partTokensFile.createNewFile(); - writeToFile(partTokensFile.toString(), "[]", false); - } - - int quorumSignVerifyCount = 0; - JSONObject quorumSignatures = null; - - ArrayList quorumDID = new ArrayList<>(); - PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); - - String receiverPeerID = getPeerID(DATA_PATH + "DID.json"); - - String receiverDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", receiverPeerID); - - listen(receiverPeerID, RECEIVER_PORT); - ss = new ServerSocket(RECEIVER_PORT); - TokenReceiverLogger.debug("Receiver Listening on " + RECEIVER_PORT + " appname " + receiverPeerID); - - sk = ss.accept(); - BufferedReader input = new BufferedReader(new InputStreamReader(sk.getInputStream())); - PrintStream output = new PrintStream(sk.getOutputStream()); - long startTime = System.currentTimeMillis(); - - try { - senderPeerID = input.readLine(); - } catch (SocketException e) { - TokenReceiverLogger.warn("Sender Stream Null - Sender Details"); - APIResponse.put("did", ""); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Sender Stream Null - Sender Details"); - - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - - } - syncDataTable(null, senderPeerID); - - swarmConnectP2P(senderPeerID, ipfs); - - String senderDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", senderPeerID); - String senderWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "peerid", senderPeerID); - - if (!(senderDidIpfsHash.contains("Qm") && senderWidIpfsHash.contains("Qm"))) { - output.println("420"); - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Sender details not available in network , please sync"); - TokenReceiverLogger.info("Sender details not available in datatable"); - - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - } - - nodeData(senderDidIpfsHash, senderWidIpfsHash, ipfs); - File senderDIDFile = new File(DATA_PATH + senderDidIpfsHash + "/DID.png"); - if (!senderDIDFile.exists()) { - output.println("420"); - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Sender details not available"); - TokenReceiverLogger.info("Sender details not available"); - /* executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); */ - - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - } - TokenReceiverLogger.debug("Sender details authenticated"); - output.println("200"); - - String tokenDetails; - try { - tokenDetails = input.readLine(); - } catch (SocketException e) { - TokenReceiverLogger.warn("Sender Stream Null - Token Details"); - APIResponse.put("did", ""); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Sender Stream Null - Token Details"); - - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - - } - JSONObject tokenObject = new JSONObject(tokenDetails); - JSONObject TokenDetails = tokenObject.getJSONObject("tokenDetails"); - JSONArray wholeTokens = TokenDetails.getJSONArray("whole-tokens"); - JSONArray wholeTokenChains = TokenDetails.getJSONArray("whole-tokenChains"); - - JSONArray partTokens = TokenDetails.getJSONArray("part-tokens"); - JSONObject partTokenChains = TokenDetails.getJSONObject("part-tokenChains"); - JSONArray partTokenChainsHash = TokenDetails.getJSONArray("hashSender"); - - JSONArray previousSendersArray = tokenObject.getJSONArray("previousSender"); - Double amount = tokenObject.getDouble("amount"); - JSONObject amountLedger = tokenObject.getJSONObject("amountLedger"); - TokenReceiverLogger.debug("Amount Ledger: " + amountLedger); - int intPart = wholeTokens.length(); - Double decimalPart = formatAmount(amount - intPart); - JSONArray doubleSpentToken = new JSONArray(); - boolean tokenOwners = true; - ArrayList ownersArray = new ArrayList(); - ArrayList previousSender = new ArrayList(); - JSONArray ownersReceived = new JSONArray(); - for (int i = 0; i < wholeTokens.length(); ++i) { - try { - TokenReceiverLogger.debug("Checking owners for " + wholeTokens.getString(i) + " Please wait..."); - ownersArray = IPFSNetwork.dhtOwnerCheck(wholeTokens.getString(i)); - - if (ownersArray.size() > 2) { - - for (int j = 0; j < previousSendersArray.length(); j++) { - if (previousSendersArray.getJSONObject(j).getString("token") - .equals(wholeTokens.getString(i))) - ownersReceived = previousSendersArray.getJSONObject(j).getJSONArray("sender"); - } - - for (int j = 0; j < ownersReceived.length(); j++) { - previousSender.add(ownersReceived.getString(j)); - } - TokenReceiverLogger.debug("Previous Owners: " + previousSender); - - for (int j = 0; j < ownersArray.size(); j++) { - if (!previousSender.contains(ownersArray.get(j).toString())) - tokenOwners = false; - } - } - } catch (IOException e) { - - TokenReceiverLogger.debug("Ipfs dht find did not execute"); - } - } - if (!tokenOwners) { - JSONArray owners = new JSONArray(); - for (int i = 0; i < ownersArray.size(); i++) - owners.put(ownersArray.get(i).toString()); - TokenReceiverLogger.debug("Multiple Owners for " + doubleSpentToken); - TokenReceiverLogger.debug("Owners: " + owners); - output.println("200"); - output.println(doubleSpentToken.toString()); - output.println(owners.toString()); - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Multiple Owners for " + doubleSpentToken + " " + owners); - IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - } - - String senderToken = TokenDetails.toString(); - String consensusID = calculateHash(senderToken, "SHA3-256"); - writeToFile(LOGGER_PATH + "consensusID", consensusID, false); - String consensusIDIPFSHash = IPFSNetwork.addHashOnly(LOGGER_PATH + "consensusID", ipfs); - deleteFile(LOGGER_PATH + "consensusID"); - - if (!IPFSNetwork.dhtEmpty(consensusIDIPFSHash, ipfs)) { - TokenReceiverLogger.debug("consensus ID not unique" + consensusIDIPFSHash); - output.println("200"); - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Consensus ID not unique"); - IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - } - - // Check IPFS get and Stake ID (signed when participated as quorum in mining) - // for all Tokens - int ipfsGetFlag = 0; - ArrayList allTokenContent = new ArrayList<>(); - ArrayList allTokenChainContent = new ArrayList<>(); - for (int i = 0; i < intPart; i++) { - String TokenChainContent = get(wholeTokenChains.getString(i), ipfs); - allTokenChainContent.add(TokenChainContent); - String TokenContent = get(wholeTokens.getString(i), ipfs); - - // ! yet to verify if we are going to use stake ID or quorum pinning token on - - // ? Steps - // ? generate stake ID for the token hash - // ? check if stake ID exists in the network for the token hash (someone must - // have staked this token for participating in mining) - // ? stake ID should be signed by the staking node to avoid malicious node - // staking tokens they dont own - // ? get mined token from stake ID - // ? if the mined token has token chain content > credits required to mine that - // token, then stake ID is not considered and token is accepted by reciever - // ? ignore the token and continue with the transaction - - allTokenContent.add(TokenContent); - ipfsGetFlag++; - } - repo(ipfs); - - if (!(ipfsGetFlag == intPart)) { - output.println("422"); - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Tokens not verified"); - TokenReceiverLogger.info("Tokens not verified"); - IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - } - - JSONArray partTokenChainContent = new JSONArray(); - JSONArray partTokenContent = new JSONArray(); - - for (int i = 0; i < partTokenChains.length(); i++) { - - partTokenChainContent.put(partTokenChains.getJSONArray(partTokens.getString(i))); - String TokenContent = get(partTokens.getString(i), ipfs); - partTokenContent.put(TokenContent); - } - - boolean chainFlag = true; - for (int i = 0; i < partTokenChainContent.length(); i++) { - JSONArray tokenChainContent = partTokenChainContent.getJSONArray(i); - for (int j = 0; j < tokenChainContent.length(); j++) { - String previousHash = tokenChainContent.getJSONObject(j).getString("previousHash"); - String nextHash = tokenChainContent.getJSONObject(j).getString("nextHash"); - String rePreviousHash, reNextHash; - if (tokenChainContent.length() > 1) { - if (j == 0) { - rePreviousHash = ""; - String rePrev = calculateHash(new JSONObject().toString(), "SHA3-256"); - reNextHash = calculateHash(tokenChainContent.getJSONObject(j + 1).getString("tid"), - "SHA3-256"); - - if (!((rePreviousHash.equals(previousHash) || rePrev.equals(previousHash)) - && reNextHash.equals(nextHash))) { - chainFlag = false; - } - - } else if (j == tokenChainContent.length() - 1) { - rePreviousHash = calculateHash(tokenChainContent.getJSONObject(j - 1).getString("tid"), - "SHA3-256"); - reNextHash = ""; - - if (!(rePreviousHash.equals(previousHash) && reNextHash.equals(nextHash))) { - chainFlag = false; - } - - } else { - rePreviousHash = calculateHash(tokenChainContent.getJSONObject(j - 1).getString("tid"), - "SHA3-256"); - reNextHash = calculateHash(tokenChainContent.getJSONObject(j + 1).getString("tid"), - "SHA3-256"); - - if (!(rePreviousHash.equals(previousHash) && reNextHash.equals(nextHash))) { - chainFlag = false; - } - } - } - } - } - if (!chainFlag) { - - String errorMessage = "Broken Cheque Chain"; - output.println("423"); - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", errorMessage); - TokenReceiverLogger.debug(errorMessage); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - } - - boolean partsAvailable = true; - for (int i = 0; i < partTokenChainContent.length(); i++) { - Double senderCount = 0.000D, receiverCount = 0.000D; - JSONArray tokenChainContent = partTokenChainContent.getJSONArray(i); - for (int k = 0; k < tokenChainContent.length(); k++) { - if (tokenChainContent.getJSONObject(k).has("role")) { - if (tokenChainContent.getJSONObject(k).getString("role").equals("Sender") - && tokenChainContent.getJSONObject(k).getString("sender").equals(senderDidIpfsHash)) { - senderCount += tokenChainContent.getJSONObject(k).getDouble("amount"); - } else if (tokenChainContent.getJSONObject(k).getString("role").equals("Receiver") - && tokenChainContent.getJSONObject(k).getString("receiver").equals(senderDidIpfsHash)) { - receiverCount += tokenChainContent.getJSONObject(k).getDouble("amount"); - } - } - } - FunctionsLogger.debug("Sender Parts: " + formatAmount(senderCount)); - FunctionsLogger.debug("Receiver Parts: " + formatAmount(receiverCount)); - Double availableParts = receiverCount - senderCount; - - availableParts = formatAmount(availableParts); - availableParts += amountLedger.getDouble(partTokens.getString(i)); - availableParts = formatAmount(availableParts); - - if (availableParts > 1.000D) { - TokenReceiverLogger.debug("Token wholly spent: " + partTokens.getString(i)); - TokenReceiverLogger.debug("Parts: " + availableParts); - } - } - - if (!partsAvailable) { - String errorMessage = "Token wholly spent already"; - output.println("424"); - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", errorMessage); - TokenReceiverLogger.debug(errorMessage); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - } else - output.println("200"); - - String senderDetails; - try { - senderDetails = input.readLine(); - } catch (SocketException e) { - TokenReceiverLogger.warn("Sender Stream Null - Sender Details"); - APIResponse.put("did", ""); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Sender Stream Null - Sender Details"); - - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - - } - JSONObject SenderDetails = new JSONObject(senderDetails); - String senderSignature = SenderDetails.getString("sign"); - String tid = SenderDetails.getString("tid"); - String comment = SenderDetails.getString("comment"); - String Status = SenderDetails.getString("status"); - String QuorumDetails = SenderDetails.getString("quorumsign"); - - BufferedImage senderWidImage = ImageIO.read(new File(DATA_PATH + senderDidIpfsHash + "/PublicShare.png")); - SenWalletBin = PropImage.img2bin(senderWidImage); - - TokenReceiverLogger.debug("Verifying Quorum ... "); - TokenReceiverLogger.debug("Please wait, this might take a few seconds"); - - if (!Status.equals("Consensus Failed")) { - boolean yesQuorum = false; - if (Status.equals("Consensus Reached")) { - quorumSignatures = new JSONObject(QuorumDetails); - String selectQuorumHash = calculateHash(senderToken, "SHA3-256"); - String verifyQuorumHash = calculateHash(selectQuorumHash.concat(receiverDidIpfsHash), "SHA3-256"); - - Iterator keys = quorumSignatures.keys(); - while (keys.hasNext()) { - String key = keys.next(); - quorumDID.add(key); - } - - for (String quorumDidIpfsHash : quorumDID) { - syncDataTable(quorumDidIpfsHash, null); - String quorumWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "didHash", - quorumDidIpfsHash); - - nodeData(quorumDidIpfsHash, quorumWidIpfsHash, ipfs); - } - - for (int i = 0; i < quorumSignatures.length(); i++) { - - JSONObject detailsForVerify = new JSONObject(); - detailsForVerify.put("did", quorumDID.get(i)); - detailsForVerify.put("hash", verifyQuorumHash); - detailsForVerify.put("signature", quorumSignatures.getString(quorumDID.get(i))); - boolean val = Authenticate.verifySignature(detailsForVerify.toString()); - if (val) - quorumSignVerifyCount++; - } - TokenReceiverLogger.debug("Verified Quorum Count " + quorumSignVerifyCount); - yesQuorum = quorumSignVerifyCount >= quorumSignatures.length(); - } - JSONArray wholeTokenChainHash = new JSONArray(); - for (int i = 0; i < intPart; i++) - wholeTokenChainHash.put(wholeTokenChains.getString(i)); - - String hash = calculateHash( - wholeTokens.toString() + wholeTokenChainHash.toString() + partTokens.toString() - + partTokenChainsHash.toString() + receiverDidIpfsHash + senderDidIpfsHash + comment, - "SHA3-256"); - TokenReceiverLogger.debug("Hash to verify Sender: " + hash); - JSONObject detailsForVerify = new JSONObject(); - detailsForVerify.put("did", senderDidIpfsHash); - detailsForVerify.put("hash", hash); - detailsForVerify.put("signature", senderSignature); - - boolean yesSender = Authenticate.verifySignature(detailsForVerify.toString()); - TokenReceiverLogger.debug("Quorum Auth : " + yesQuorum + " Sender Auth : " + yesSender); - if (!(yesSender && yesQuorum)) { - output.println("420"); - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", tid); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Sender / Quorum not verified"); - TokenReceiverLogger.info("Sender / Quorum not verified"); - IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - } - - repo(ipfs); - TokenReceiverLogger.debug("Sender and Quorum Verified"); - output.println("200"); - - String pinDetails; - try { - pinDetails = input.readLine(); - } catch (SocketException e) { - TokenReceiverLogger.warn("Sender Stream Null - Pinning Status"); - APIResponse.put("did", ""); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Sender Stream Null - Pinning Status"); - - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - - } - if (pinDetails.equals("Unpinned")) { - int count = 0; - for (int i = 0; i < intPart; i++) { - FileWriter fileWriter; - fileWriter = new FileWriter(TOKENS_PATH + wholeTokens.getString(i)); - fileWriter.write(allTokenContent.get(i)); - fileWriter.close(); - add(TOKENS_PATH + wholeTokens.getString(i), ipfs); - pin(wholeTokens.getString(i), ipfs); - count++; - - } - - for (int i = 0; i < partTokens.length(); i++) { - File tokenFile = new File(PART_TOKEN_PATH + partTokens.getString(i)); - if (!tokenFile.exists()) - tokenFile.createNewFile(); - FileWriter fileWriter; - fileWriter = new FileWriter(PART_TOKEN_PATH + partTokens.getString(i)); - fileWriter.write(partTokenContent.getString(i)); - fileWriter.close(); - String tokenHash = add(PART_TOKEN_PATH + partTokens.getString(i), ipfs); - pin(tokenHash, ipfs); - - } - - if (count == intPart) { - TokenReceiverLogger.debug("Pinned All Tokens"); - output.println("Successfully Pinned"); - - String essentialShare; - try { - essentialShare = input.readLine(); - } catch (SocketException e) { - TokenReceiverLogger.warn("Sender Stream Null - EShare Details"); - APIResponse.put("did", ""); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Sender Stream Null - EShare Details"); - - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - - } - long endTime = System.currentTimeMillis(); - - for (int i = 0; i < intPart; i++) { - - ArrayList groupTokens = new ArrayList<>(); - for (int k = 0; k < intPart; k++) { - if (!wholeTokens.getString(i).equals(wholeTokens.getString(k))) - groupTokens.add(wholeTokens.getString(k)); - } - - JSONArray arrToken = new JSONArray(); - JSONObject objectToken = new JSONObject(); - objectToken.put("tokenHash", wholeTokens.getString(i)); - arrToken.put(objectToken); - JSONArray arr1 = new JSONArray(allTokenChainContent.get(i)); - JSONObject obj2 = new JSONObject(); - obj2.put("senderSign", senderSignature); - obj2.put("sender", senderDidIpfsHash); - obj2.put("group", groupTokens); - obj2.put("comment", comment); - obj2.put("tid", tid); - arr1.put(obj2); - writeToFile(TOKENCHAIN_PATH + wholeTokens.getString(i) + ".json", arr1.toString(), false); - } - - for (int i = 0; i < partTokens.length(); i++) { - JSONObject chequeObject = new JSONObject(); - chequeObject.put("sender", senderDidIpfsHash); - chequeObject.put("receiver", receiverDidIpfsHash); - chequeObject.put("parent-token", partTokens.getString(i)); - chequeObject.put("parent-chain", partTokenChains.getJSONArray(partTokens.getString(i))); - Double partAmount = formatAmount(amountLedger.getDouble(partTokens.getString(i))); - chequeObject.put("amount", partAmount); - chequeObject.put("tid", tid); - - writeToFile(LOGGER_PATH.concat(partTokens.getString(i)), chequeObject.toString(), false); - String chequeHash = IPFSNetwork.add(LOGGER_PATH.concat(partTokens.getString(i)), ipfs); - deleteFile(LOGGER_PATH.concat(partTokens.getString(i))); - - JSONObject newPartObject = new JSONObject(); - newPartObject.put("senderSign", senderSignature); - newPartObject.put("sender", senderDidIpfsHash); - newPartObject.put("receiver", receiverDidIpfsHash); - newPartObject.put("comment", comment); - newPartObject.put("tid", tid); - newPartObject.put("nextHash", ""); - if (partTokenChainContent.getJSONArray(i).length() == 0) - newPartObject.put("previousHash", ""); - else - newPartObject.put("previousHash", - calculateHash(partTokenChainContent.getJSONArray(i) - .getJSONObject(partTokenChainContent.getJSONArray(i).length() - 1) - .getString("tid"), "SHA3-256")); - - newPartObject.put("amount", partAmount); - newPartObject.put("cheque", chequeHash); - newPartObject.put("role", "Receiver"); - - File chainFile = new File( - PART_TOKEN_CHAIN_PATH.concat(partTokens.getString(i)).concat(".json")); - if (chainFile.exists()) { - - String readChain = readFile(PART_TOKEN_CHAIN_PATH + partTokens.getString(i) + ".json"); - JSONArray readChainArray = new JSONArray(readChain); - readChainArray.put(partTokenChainContent.getJSONArray(i) - .getJSONObject(partTokenChainContent.getJSONArray(i).length() - 1)); - readChainArray.put(newPartObject); - - writeToFile(PART_TOKEN_CHAIN_PATH + partTokens.getString(i) + ".json", - readChainArray.toString(), false); - - } else { - partTokenChainContent.getJSONArray(i).put(newPartObject); - writeToFile(PART_TOKEN_CHAIN_PATH + partTokens.getString(i) + ".json", - partTokenChainContent.getJSONArray(i).toString(), false); - } - } - - JSONObject transactionRecord = new JSONObject(); - transactionRecord.put("role", "Receiver"); - transactionRecord.put("tokens", wholeTokens); - transactionRecord.put("txn", tid); - transactionRecord.put("quorumList", quorumSignatures.keys()); - transactionRecord.put("senderDID", senderDidIpfsHash); - transactionRecord.put("receiverDID", receiverDidIpfsHash); - transactionRecord.put("Date", getCurrentUtcTime()); - transactionRecord.put("totalTime", (endTime - startTime)); - transactionRecord.put("comment", comment); - transactionRecord.put("essentialShare", essentialShare); - amount = formatAmount(amount); - transactionRecord.put("amount-received", amount); - - JSONArray transactionHistoryEntry = new JSONArray(); - transactionHistoryEntry.put(transactionRecord); - updateJSON("add", WALLET_DATA_PATH + "TransactionHistory.json", - transactionHistoryEntry.toString()); - - for (int i = 0; i < wholeTokens.length(); i++) { - String bankFile = readFile(PAYMENTS_PATH.concat("BNK00.json")); - JSONArray bankArray = new JSONArray(bankFile); - JSONObject tokenObject1 = new JSONObject(); - tokenObject1.put("tokenHash", wholeTokens.getString(i)); - bankArray.put(tokenObject1); - Functions.writeToFile(PAYMENTS_PATH.concat("BNK00.json"), bankArray.toString(), false); - - } - - String partsFile = readFile(PAYMENTS_PATH.concat("PartsToken.json")); - JSONArray partsReadArray = new JSONArray(partsFile); - - for (int i = 0; i < partTokens.length(); i++) { - boolean writeParts = true; - for (int j = 0; j < partsReadArray.length(); j++) { - if (partsReadArray.getJSONObject(j).getString("tokenHash") - .equals(partTokens.getString(i))) - writeParts = false; - } - if (writeParts) { - JSONObject partObject = new JSONObject(); - partObject.put("tokenHash", partTokens.getString(i)); - partsReadArray.put(partObject); - } - } - writeToFile(PAYMENTS_PATH.concat("PartsToken.json"), partsReadArray.toString(), false); - - TokenReceiverLogger.info("Transaction ID: " + tid + "Transaction Successful"); - output.println("Send Response"); - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", tid); - APIResponse.put("status", "Success"); - APIResponse.put("tokens", wholeTokens); - APIResponse.put("comment", comment); - APIResponse.put("message", "Transaction Successful"); - TokenReceiverLogger.info(" Transaction Successful"); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - - } - output.println("count mistmatch"); - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "count mismacth"); - TokenReceiverLogger.info(" Transaction failed"); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - - } - - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Failed to unpin"); - TokenReceiverLogger.info(" Transaction failed"); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - - } - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", "null"); - APIResponse.put("status", "Failed"); - APIResponse.put("message", "Consensus failed at Sender side"); - TokenReceiverLogger.info(" Transaction failed"); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - output.close(); - input.close(); - sk.close(); - ss.close(); - return APIResponse.toString(); - - } catch (Exception e) { - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - TokenReceiverLogger.error("Exception Occurred", e); - return APIResponse.toString(); - } finally { - try { - ss.close(); - sk.close(); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - } catch (Exception e) { - executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); - TokenReceiverLogger.error("Exception Occurred", e); - } - - } - } + public static Logger TokenReceiverLogger = Logger.getLogger(TokenReceiver.class); + + private static final JSONObject APIResponse = new JSONObject(); + private static IPFS ipfs = new IPFS("/ip4/127.0.0.1/tcp/" + IPFS_PORT); + private static String SenWalletBin; + + // token limit for each level + private static final int[] tokenLimit = { 0, 5000000, 2425000, 2303750, 2188563, 2079134, 1975178, 1876419, 1782598, + 1693468, 1608795, 1528355, 1451937, 1379340 }; + + /** + * Receiver Node: To receive a valid token from an authentic sender + * + * @return Transaction Details (JSONObject) + * @throws IOException handles IO Exceptions + * @throws JSONException handles JSON Exceptions + */ + public static String receive() { + pathSet(); + ServerSocket ss = null; + Socket sk = null; + String senderPeerID = null; + + try { + repo(ipfs); + String PART_TOKEN_CHAIN_PATH = TOKENCHAIN_PATH.concat("PARTS/"); + String PART_TOKEN_PATH = TOKENS_PATH.concat("PARTS/"); + File partFolder = new File(PART_TOKEN_PATH); + if (!partFolder.exists()) + partFolder.mkdir(); + partFolder = new File(PART_TOKEN_CHAIN_PATH); + if (!partFolder.exists()) + partFolder.mkdir(); + File partTokensFile = new File(PAYMENTS_PATH.concat("PartsToken.json")); + if (!partTokensFile.exists()) { + partTokensFile.createNewFile(); + writeToFile(partTokensFile.toString(), "[]", false); + } + + int quorumSignVerifyCount = 0; + JSONObject quorumSignatures = null; + + ArrayList quorumDID = new ArrayList<>(); + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + + String receiverPeerID = getPeerID(DATA_PATH + "DID.json"); + + String receiverDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", receiverPeerID); + + listen(receiverPeerID, RECEIVER_PORT); + ss = new ServerSocket(RECEIVER_PORT); + TokenReceiverLogger.debug("Receiver Listening on " + RECEIVER_PORT + " appname " + receiverPeerID); + + sk = ss.accept(); + TokenReceiverLogger.debug("Data Incoming..."); + BufferedReader input = new BufferedReader(new InputStreamReader(sk.getInputStream())); + PrintStream output = new PrintStream(sk.getOutputStream()); + long startTime = System.currentTimeMillis(); + + try { + senderPeerID = input.readLine(); + } catch (SocketException e) { + TokenReceiverLogger.warn("Sender Stream Null - Sender Details"); + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender Stream Null - Sender Details"); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + TokenReceiverLogger.debug("Data Received: " + senderPeerID); + swarmConnectP2P(senderPeerID, ipfs); + + String senderDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", senderPeerID); + String senderWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "peerid", senderPeerID); + + if (!(senderDidIpfsHash.contains("Qm") && senderWidIpfsHash.contains("Qm"))) { + output.println("420"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender details not available in network , please sync"); + TokenReceiverLogger.info("Sender details not available in datatable"); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + nodeData(senderDidIpfsHash, senderWidIpfsHash, ipfs); + File senderDIDFile = new File(DATA_PATH + senderDidIpfsHash + "/DID.png"); + if (!senderDIDFile.exists()) { + output.println("420"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender details not available"); + TokenReceiverLogger.info("Sender details not available"); + /* executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); */ + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + TokenReceiverLogger.debug("Sender details authenticated"); + output.println("200"); + + String tokenDetails; + try { + tokenDetails = input.readLine(); + } catch (SocketException e) { + TokenReceiverLogger.warn("Sender Stream Null - Token Details"); + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender Stream Null - Token Details"); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + JSONObject tokenObject = new JSONObject(tokenDetails); + JSONObject TokenDetails = tokenObject.getJSONObject("tokenDetails"); + JSONArray wholeTokens = TokenDetails.getJSONArray("whole-tokens"); + JSONArray wholeTokenChains = TokenDetails.getJSONArray("whole-tokenChains"); + + JSONArray partTokens = TokenDetails.getJSONArray("part-tokens"); + JSONObject partTokenChains = TokenDetails.getJSONObject("part-tokenChains"); + JSONArray partTokenChainsHash = TokenDetails.getJSONArray("hashSender"); + + JSONArray previousSendersArray = tokenObject.getJSONArray("previousSender"); + JSONArray positionsArray = tokenObject.getJSONArray("positions"); + + Double amount = tokenObject.getDouble("amount"); + JSONObject amountLedger = tokenObject.getJSONObject("amountLedger"); + TokenReceiverLogger.debug("Amount Ledger: " + amountLedger); + int intPart = wholeTokens.length(); + // ? multiple pin check starts + Double decimalPart = formatAmount(amount - intPart); + JSONArray doubleSpentToken = new JSONArray(); + boolean tokenOwners = true; + ArrayList pinOwnersArray = new ArrayList(); + ArrayList previousSender = new ArrayList(); + JSONArray ownersReceived = new JSONArray(); + TokenReceiverLogger.debug("previousSendersArray is " + previousSendersArray.toString()); + TokenReceiverLogger.debug("tokenObject is " + tokenObject.toString()); + TokenReceiverLogger.debug("tokenDetails(base for tokenObj) is " + tokenDetails.toString()); + + // previoussenderarray + // tokenobject + for (int i = 0; i < wholeTokens.length(); ++i) { + try { + TokenReceiverLogger.debug("Checking owners for " + wholeTokens.getString(i) + " Please wait..."); + pinOwnersArray = IPFSNetwork.dhtOwnerCheck(wholeTokens.getString(i)); + + if (pinOwnersArray.size() > 2) { + + for (int j = 0; j < previousSendersArray.length(); j++) { + if (previousSendersArray.getJSONObject(j).getString("token") + .equals(wholeTokens.getString(i))) + ownersReceived = previousSendersArray.getJSONObject(j).getJSONArray("sender"); + } + + for (int j = 0; j < ownersReceived.length(); j++) { + previousSender.add(ownersReceived.getString(j)); + } + TokenReceiverLogger.debug("Previous Owners: " + previousSender); + + for (int j = 0; j < pinOwnersArray.size(); j++) { + if (!previousSender.contains(pinOwnersArray.get(j).toString())) + tokenOwners = false; + } + } + } catch (IOException e) { + + TokenReceiverLogger.debug("Ipfs dht find did not execute"); + } + } + if (!tokenOwners) { + JSONArray owners = new JSONArray(); + for (int i = 0; i < pinOwnersArray.size(); i++) + owners.put(pinOwnersArray.get(i).toString()); + TokenReceiverLogger.debug("Multiple Owners for " + doubleSpentToken); + TokenReceiverLogger.debug("Owners: " + owners); + output.println("420"); + output.println(doubleSpentToken.toString()); + output.println(owners.toString()); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Multiple Owners for " + doubleSpentToken + " " + owners); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + // ? multiple pin check ends + String senderToken = TokenDetails.toString(); + String consensusID = calculateHash(senderToken, "SHA3-256"); + writeToFile(LOGGER_PATH + "consensusID", consensusID, false); + String consensusIDIPFSHash = IPFSNetwork.addHashOnly(LOGGER_PATH + "consensusID", ipfs); + deleteFile(LOGGER_PATH + "consensusID"); + + if (!IPFSNetwork.dhtEmpty(consensusIDIPFSHash, ipfs)) { + TokenReceiverLogger.debug("consensus ID not unique" + consensusIDIPFSHash); + output.println("421"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Consensus ID not unique"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + // Check IPFS get for all Tokens + int ipfsGetFlag = 0; + ArrayList wholeTokenContent = new ArrayList<>(); + ArrayList wholeTokenChainContent = new ArrayList<>(); + + /** Token Authenticity Check - starts */ + HashMap tokenMaxLimitMap = new HashMap<>(); + HashMap tokenDetailMap = new HashMap<>(); + + for (int i = 0; i < wholeTokens.length(); i++) { + + String tokenChainContent = get(wholeTokenChains.getString(i), ipfs); + wholeTokenChainContent.add(tokenChainContent); + String tokenContent = get(wholeTokens.getString(i), ipfs).trim(); + wholeTokenContent.add(tokenContent); + ipfsGetFlag++; + String tokenLevel = tokenContent.substring(0, tokenContent.length() - 64); + String tokenNumberHash = tokenContent.substring(tokenContent.length() - 64); + + int tokenLevelInt = Integer.parseInt(tokenLevel); + int tokenLimitForLevel = tokenLimit[tokenLevelInt]; + tokenMaxLimitMap.put(tokenNumberHash, tokenLimitForLevel); + tokenDetailMap.put(tokenNumberHash, -1); + } + repo(ipfs); + + if (wholeTokens.length() > 0) { + + if (!(ipfsGetFlag == intPart)) { + output.println("422"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Tokens not verified"); + TokenReceiverLogger.info("Tokens not verified"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + int tokenMaxValue = Collections.max(tokenMaxLimitMap.values()); + TokenReceiverLogger.debug("Token Max Value : " + tokenMaxValue); + tokenDetailMap = Functions.checkTokenHash(tokenDetailMap, tokenMaxValue); + + if (tokenDetailMap.isEmpty()) { + TokenReceiverLogger.debug("Invalid Content Found in Token"); + String errorMessage = "Invalid Content Found in Token"; + output.println("426"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", errorMessage); + TokenReceiverLogger.debug(errorMessage); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } else { + for (String tokenContent : tokenDetailMap.keySet()) { + TokenReceiverLogger.debug(tokenContent); + TokenReceiverLogger.debug(tokenDetailMap.get(tokenContent)); + TokenReceiverLogger.debug(tokenMaxLimitMap.get(tokenContent)); + + if (tokenDetailMap.get(tokenContent) != null + && tokenDetailMap.get(tokenContent) > tokenMaxLimitMap.get(tokenContent)) { + + output.println("426"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + String errorMessage1 = "Token Number is greater than Token Limit for the Level"; + APIResponse.put("message", errorMessage1); + TokenReceiverLogger.debug(errorMessage1); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + } + } + + } + /** Token Authenticity Check - Ends */ + + JSONArray partTokenChainContent = new JSONArray(); + JSONArray partTokenContent = new JSONArray(); + + for (int i = 0; i < partTokenChains.length(); i++) { + + partTokenChainContent.put(partTokenChains.getJSONArray(partTokens.getString(i))); + String TokenContent = get(partTokens.getString(i), ipfs).trim(); + partTokenContent.put(TokenContent); + } + + boolean chainFlag = true; + for (int i = 0; i < partTokenChainContent.length(); i++) { + JSONArray tokenChainContent = partTokenChainContent.getJSONArray(i); + for (int j = 0; j < tokenChainContent.length(); j++) { + String previousHash = tokenChainContent.getJSONObject(j).getString("previousHash"); + String nextHash = tokenChainContent.getJSONObject(j).getString("nextHash"); + String rePreviousHash, reNextHash; + if (tokenChainContent.length() > 1) { + if (j == 0) { + rePreviousHash = ""; + String rePrev = calculateHash(new JSONObject().toString(), "SHA3-256"); + reNextHash = calculateHash(tokenChainContent.getJSONObject(j + 1).getString("tid"), + "SHA3-256"); + + if (!((rePreviousHash.equals(previousHash) || rePrev.equals(previousHash)) + && reNextHash.equals(nextHash))) { + chainFlag = false; + } + + } else if (j == tokenChainContent.length() - 1) { + rePreviousHash = calculateHash(tokenChainContent.getJSONObject(j - 1).getString("tid"), + "SHA3-256"); + reNextHash = ""; + + if (!(rePreviousHash.equals(previousHash) && reNextHash.equals(nextHash))) { + chainFlag = false; + } + + } else { + rePreviousHash = calculateHash(tokenChainContent.getJSONObject(j - 1).getString("tid"), + "SHA3-256"); + reNextHash = calculateHash(tokenChainContent.getJSONObject(j + 1).getString("tid"), + "SHA3-256"); + + if (!(rePreviousHash.equals(previousHash) && reNextHash.equals(nextHash))) { + chainFlag = false; + } + } + } + } + } + + if (!chainFlag) { + String errorMessage = "Broken Cheque Chain"; + output.println("423"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", errorMessage); + TokenReceiverLogger.debug(errorMessage); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + boolean ownerCheck = true; + + JSONArray allTokens = new JSONArray(); + for (int i = 0; i < wholeTokens.length(); i++) + allTokens.put(wholeTokens.getString(i)); + for (int i = 0; i < partTokens.length(); i++) + allTokens.put(partTokens.getString(i)); + + JSONArray allTokensChains = new JSONArray(); + for (int i = 0; i < wholeTokenChainContent.size(); i++) + allTokensChains.put(wholeTokenChainContent.get(i)); + for (int i = 0; i < partTokenChainContent.length(); i++) + allTokensChains.put(partTokenChainContent.get(i)); + + TokenReceiverLogger.debug("allTokenChain is "+allTokensChains.toString()); + + + JSONArray invalidTokens = new JSONArray(); + + for (int count = 0; count < wholeTokens.length(); count++) { + String tokens = null; + TokenReceiverLogger.debug("Json array tokenChain value is " + wholeTokens.get(count).toString()); + JSONArray tokenChain = new JSONArray(allTokensChains.get(count).toString()); + TokenReceiverLogger.debug("tokenchain is " + tokenChain); + TokenReceiverLogger.debug("tokenchain size is " + tokenChain.length()); + + String tokenContent = get(wholeTokens.getString(count), ipfs).trim(); + String tokenLevel = tokenContent.substring(0, tokenContent.length() - 64); + String tokenNumberHash = tokenContent.substring(tokenContent.length() - 64); + + int tokenLevelInt = Integer.parseInt(tokenLevel); + int tokenLimitForLevel = tokenLimit[tokenLevelInt]; + int tokenLevelValue = (int) Math.pow(2, tokenLevelInt + 2); + int minumumStakeHeight = tokenLevelValue * 4; + + // ! check quorum signs for previous transaction for the tokenchain to verify + // ! the ownership of sender for the token + JSONObject lastObject = new JSONObject(); + + if (tokenChain.length() > 0 ) { + + lastObject = tokenChain.getJSONObject(tokenChain.length() - 1); + + } + TokenReceiverLogger.debug("Last Object = " + lastObject.toString()); + + + if (tokenChain.length() > 0 && lastObject.has("owner") && !lastObject.has(MiningConstants.STAKED_TOKEN) && + ( (tokenLevelInt == 4 && (tokenDetailMap.get(tokenNumberHash) >= 1204400)) || (tokenLevelInt >= 5)) ) { + + TokenReceiverLogger.debug("Checking ownership"); + String owner = lastObject.getString("owner"); + tokens = allTokens.getString(count); + String hashString = tokens.concat(senderDidIpfsHash); + String hashForPositions = calculateHash(hashString, "SHA3-256"); + String ownerIdentity = hashForPositions.concat(positionsArray.getString(count)); + String ownerRecalculated = calculateHash(ownerIdentity, "SHA3-256"); + + TokenReceiverLogger.debug("Ownership Here Sender Calculation"); + TokenReceiverLogger.debug("tokens: " + tokens); + TokenReceiverLogger.debug("hashString: " + hashString); + TokenReceiverLogger.debug("hashForPositions: " + hashForPositions); + TokenReceiverLogger.debug("p1: " + positionsArray.getString(count)); + TokenReceiverLogger.debug("ownerIdentity: " + ownerIdentity); + TokenReceiverLogger.debug("ownerIdentityHash: " + ownerRecalculated); + + if (!owner.equals(ownerRecalculated)) { + ownerCheck = false; + invalidTokens.put(tokens); + } + + if (ownerCheck && (tokenChain.length() < minumumStakeHeight)) { + // && (tokenNumber > 1204400) + JSONObject genesiObject = tokenChain.getJSONObject(0); + JSONArray stakeDataArray = genesiObject.getJSONArray(MiningConstants.MINE_ID); + + int randomNumber = new Random().nextInt(15); + JSONObject genesisSignaturesContent = genesiObject + .getJSONObject(MiningConstants.QUORUM_SIGN_CONTENT); + Iterator randomKey = genesisSignaturesContent.keys(); + for (int i = 0; i < randomNumber; i++) { + randomKey.next(); + } + /** + * String randomKeyString = randomKey.next().toString(); JSONObject + * verificationPick = new JSONObject(); verificationPick.put("did", + * randomKeyString); verificationPick.put("hash", + * genesiObject.getString("tid")); verificationPick.put("signature", + * genesisSignaturesContent.getString(randomKeyString)); + * + * if (verificationPick.getString("hash").equals(genesiObject.getString("tid"))) + * { + * + * if (Authenticate.verifySignature(verificationPick.toString())) { + * TokenReceiverLogger.debug("Staking check (3) successful"); } else { + * TokenReceiverLogger.debug( "Staking check (3) failed: Could not verify + * genesis credit signature"); ownerCheck = false; invalidTokens.put(tokens); } + * } else { TokenReceiverLogger.debug( "Staking check (3) failed: Genesis TID is + * not equal to the hash of the genesis signature"); ownerCheck = false; + * invalidTokens.put(tokens); } + */ + // else { + // TokenReceiverLogger.debug("Staking check (3) failed: Genesis Signature not + // found"); + // ownerCheck = false; + // invalidTokens.put(tokens); + // } + + if (stakeDataArray.length() == 3) { + + JSONObject oneOfThreeStake = stakeDataArray.getJSONObject(0); + JSONObject twoOfThreeStake = stakeDataArray.getJSONObject(1); + JSONObject threeOfThreeStake = stakeDataArray.getJSONObject(2); + + String[] stakedTokenTC = new String[3]; + String[] stakedTokenSignTC = new String[3]; + String[] stakerDIDTC = new String[3]; + String[] mineIDTC = new String[3]; + String[] mineIDSignTC = new String[3]; + + stakedTokenTC[0] = oneOfThreeStake.getString(MiningConstants.STAKED_TOKEN); + stakedTokenSignTC[0] = oneOfThreeStake.getString(MiningConstants.STAKED_TOKEN_SIGN); + stakerDIDTC[0] = oneOfThreeStake.getString(MiningConstants.STAKED_QUORUM_DID); + mineIDTC[0] = oneOfThreeStake.getString(MiningConstants.MINE_ID); + mineIDSignTC[0] = oneOfThreeStake.getString(MiningConstants.MINE_ID_SIGN); + + stakedTokenTC[1] = twoOfThreeStake.getString(MiningConstants.STAKED_TOKEN); + stakedTokenSignTC[1] = twoOfThreeStake.getString(MiningConstants.STAKED_TOKEN_SIGN); + stakerDIDTC[1] = twoOfThreeStake.getString(MiningConstants.STAKED_QUORUM_DID); + mineIDTC[1] = twoOfThreeStake.getString(MiningConstants.MINE_ID); + mineIDSignTC[1] = twoOfThreeStake.getString(MiningConstants.MINE_ID_SIGN); + + stakedTokenTC[2] = threeOfThreeStake.getString(MiningConstants.STAKED_TOKEN); + stakedTokenSignTC[2] = threeOfThreeStake.getString(MiningConstants.STAKED_TOKEN_SIGN); + stakerDIDTC[2] = threeOfThreeStake.getString(MiningConstants.STAKED_QUORUM_DID); + mineIDTC[2] = threeOfThreeStake.getString(MiningConstants.MINE_ID); + mineIDSignTC[2] = threeOfThreeStake.getString(MiningConstants.MINE_ID_SIGN); + TokenReceiverLogger.debug("mineIDTC length is "+mineIDTC.length); + + for (int stakeCount = 0; stakeCount < mineIDTC.length; stakeCount++) { + + String mineIDContent = get(mineIDTC[stakeCount], ipfs); + JSONObject mineIDContentJSON = new JSONObject(mineIDContent); + TokenReceiverLogger.debug(mineIDContentJSON.toString()); + + JSONObject stakeData = mineIDContentJSON.getJSONObject(MiningConstants.STAKE_DATA); + + String stakerDIDMineData = stakeData.getString(MiningConstants.STAKED_QUORUM_DID); + String stakedTokenMineData = stakeData.getString(MiningConstants.STAKED_TOKEN); + String stakedTokenSignMineData = stakeData + .getString(MiningConstants.STAKED_TOKEN_SIGN); + + TokenReceiverLogger.debug(stakerDIDTC[stakeCount]); + TokenReceiverLogger.debug(stakedTokenTC[stakeCount]); + TokenReceiverLogger.debug(stakedTokenSignTC[stakeCount]); + + TokenReceiverLogger.debug(stakerDIDMineData); + TokenReceiverLogger.debug(stakedTokenMineData); + TokenReceiverLogger.debug(stakedTokenSignMineData); + + if (stakerDIDTC[stakeCount].equals(stakerDIDMineData) + && stakedTokenTC[stakeCount].equals(stakedTokenMineData) + && stakedTokenSignTC[stakeCount].equals(stakedTokenSignMineData)) { + + TokenReceiverLogger.debug("array n non array data are same"); + + JSONObject detailsToVerify = new JSONObject(); + detailsToVerify.put("did", stakerDIDTC[stakeCount]); + detailsToVerify.put("hash", mineIDTC[stakeCount]); + detailsToVerify.put("signature", mineIDSignTC[stakeCount]); + TokenReceiverLogger.debug("detailsToVerify - "+detailsToVerify.toString()); + + if (Authenticate.verifySignature(detailsToVerify.toString())) { + + boolean minedTokenStatus = true; + ArrayList ownersArray = IPFSNetwork + .dhtOwnerCheck(stakedTokenTC[stakeCount]); + TokenReceiverLogger.debug("dht owner are "+ownersArray.toString()+" size is "+ownersArray.size()); + for (int i = 0; i < ownersArray.size(); i++) { + if (ownersArray.get(i).equals(stakerDIDTC[stakeCount])) { + minedTokenStatus = false; + } + } + if (!minedTokenStatus) { + TokenReceiverLogger.debug("Staked token is not found with staker DID: " + + stakerDIDTC[stakeCount]); + ownerCheck = false; + invalidTokens.put(tokens); + } + + } else { + TokenReceiverLogger.debug( + "Staking check (2) failed - unable to verify mine ID signature by staker: " + + stakerDIDTC[stakeCount]); + ownerCheck = false; + invalidTokens.put(tokens); + } + + TokenReceiverLogger.debug("MineID Verification Successful with Staking node: " + + stakerDIDTC[stakeCount]); + } else { + TokenReceiverLogger.debug("Staking check (2) failed"); + ownerCheck = false; + invalidTokens.put(tokens); + } + + TokenReceiverLogger.debug("Staking check (2) successful for count "+stakeCount); + // } else { + // TokenReceiverLogger.debug( + // "Staking check (2) failed: Could not verify mine ID signature"); + // ownerCheck = false; + // invalidTokens.put(tokens); + // } + } + + } else { + ownerCheck = false; + TokenReceiverLogger.debug("Staked Token is not available!"); + + } + + } + } + else if (tokenChain.length() > 0 && lastObject.has(MiningConstants.STAKED_TOKEN)) { + + Boolean minedTokenStatus = true; + + String mineID = lastObject.getString(MiningConstants.MINE_ID); + + String mineIDContent = get(mineID, ipfs); + JSONObject mineIDContentJSON = new JSONObject(mineIDContent); + + JSONObject stakeData = mineIDContentJSON.getJSONObject(MiningConstants.STAKE_DATA); + + ArrayList ownersArray = IPFSNetwork + .dhtOwnerCheck(stakeData.getString(MiningConstants.STAKED_TOKEN)); + for (int i = 0; i < ownersArray.size(); i++) { + if (!VerifyStakedToken.Contact(ownersArray.get(i), SEND_PORT + 16, + stakeData.getString(MiningConstants.STAKED_TOKEN), + mineIDContentJSON.getString("tokenContent"))) { + minedTokenStatus = false; + } + } + if (!minedTokenStatus) { + TokenReceiverLogger.debug("Staking check failed: Found staked token but token height < 46"); + ownerCheck = false; + invalidTokens.put(tokens); + } + + TokenReceiverLogger.debug( + "Staking check failed: Found staked token but unable to transfer while mined token height is not satisfied for the network"); + ownerCheck = false; + invalidTokens.put(tokens); + + // JSONObject tokenToVerify = new JSONObject(); + // if (mineIDContentJSON.has(MiningConstants.STAKE_DATA)) { + + // JSONObject stakeData = + // mineIDContentJSON.getJSONObject(MiningConstants.STAKE_DATA); + // String stakerDID = stakeData.getString(STAKED_QUORUM_DID); + // String stakedToken = stakeData.getString(STAKED_TOKEN); + // String stakedTokenSign = stakeData.getString(STAKED_TOKEN_SIGN); + + // tokenToVerify.put("did", senderDidIpfsHash); + // tokenToVerify.put("hash", stakedToken); + // tokenToVerify.put("signature", stakedTokenSign); + + // if (Authenticate.verifySignature(tokenToVerify.toString())) { + + // ArrayList ownersArray = IPFSNetwork.dhtOwnerCheck(stakedToken); + // for (int i = 0; i < ownersArray.size(); i++) { + // if (!VerifyStakedToken.Contact(ownersArray.get(i), SEND_PORT + 16, + // mineIDContentJSON.getString("tokenContent"))) { + // minedTokenStatus = false; + // } + // } + // if (!minedTokenStatus) { + // TokenReceiverLogger + // .debug("Staking check failed: Found staked token but token height < 46"); + // ownerCheck = false; + // invalidTokens.put(tokens); + // } + + // TokenReceiverLogger.debug( + // "Staking check failed: Found staked token but unable to transfer while mined + // token height is not satisfied for the network"); + // ownerCheck = false; + // invalidTokens.put(tokens); + + // } else { + // TokenReceiverLogger.debug( + // "Staking check failed: Found staked token but unable to verify staked token + // height"); + // ownerCheck = false; + // invalidTokens.put(tokens); + // } + // } + + } + + } + + if (!ownerCheck) { + TokenReceiverLogger.debug("Ownership Check Failed"); + String errorMessage = "Ownership Check Failed"; + output.println("424"); + output.println(invalidTokens.toString()); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", errorMessage); + TokenReceiverLogger.debug(errorMessage); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } else + TokenReceiverLogger.debug("Ownership Check Passed"); + + // ------------------------------------------------------- + + boolean partsAvailable = true; + for (int i = 0; i < partTokenChainContent.length(); i++) { + Double senderCount = 0.000D, receiverCount = 0.000D; + JSONArray tokenChainContent = partTokenChainContent.getJSONArray(i); + for (int k = 0; k < tokenChainContent.length(); k++) { + if (tokenChainContent.getJSONObject(k).has("role")) { + if (tokenChainContent.getJSONObject(k).getString("role").equals("Sender") + && tokenChainContent.getJSONObject(k).getString("sender").equals(senderDidIpfsHash)) { + senderCount += tokenChainContent.getJSONObject(k).getDouble("amount"); + } else if (tokenChainContent.getJSONObject(k).getString("role").equals("Receiver") + && tokenChainContent.getJSONObject(k).getString("receiver").equals(senderDidIpfsHash)) { + receiverCount += tokenChainContent.getJSONObject(k).getDouble("amount"); + } + } + } + FunctionsLogger.debug("Sender Parts: " + formatAmount(senderCount)); + FunctionsLogger.debug("Receiver Parts: " + formatAmount(receiverCount)); + Double availableParts = receiverCount - senderCount; + + availableParts = formatAmount(availableParts); + availableParts += amountLedger.getDouble(partTokens.getString(i)); + availableParts = formatAmount(availableParts); + + if (availableParts > 1.000D) { + TokenReceiverLogger.debug("Token wholly spent: " + partTokens.getString(i)); + TokenReceiverLogger.debug("Parts: " + availableParts); + partsAvailable = false; + } + } + if (!partsAvailable) { + String errorMessage = "Token wholly spent already"; + output.println("425"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", errorMessage); + TokenReceiverLogger.debug(errorMessage); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + output.println("200"); + + String senderDetails; + try { + senderDetails = input.readLine(); + } catch (SocketException e) { + TokenReceiverLogger.warn("Sender Stream Null - Sender Details"); + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender Stream Null - Sender Details"); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + JSONObject SenderDetails = new JSONObject(senderDetails); + String senderSignature = SenderDetails.getString("sign"); + String tid = SenderDetails.getString("tid"); + String comment = SenderDetails.getString("comment"); + String Status = SenderDetails.getString("status"); + String QuorumDetails = SenderDetails.getString("quorumsign"); + + BufferedImage senderWidImage = ImageIO.read(new File(DATA_PATH + senderDidIpfsHash + "/PublicShare.png")); + SenWalletBin = PropImage.img2bin(senderWidImage); + + TokenReceiverLogger.debug("Verifying Quorum ... "); + TokenReceiverLogger.debug("Please wait, this might take a few seconds"); + + if (!Status.equals("Consensus Failed")) { + boolean yesQuorum = false; + if (Status.equals("Consensus Reached")) { + quorumSignatures = new JSONObject(QuorumDetails); + String selectQuorumHash = calculateHash(senderToken, "SHA3-256"); + String verifyQuorumHash = calculateHash(selectQuorumHash.concat(receiverDidIpfsHash), "SHA3-256"); + + Iterator keys = quorumSignatures.keys(); + while (keys.hasNext()) { + String key = keys.next(); + quorumDID.add(key); + } + + for (String quorumDidIpfsHash : quorumDID) { + syncDataTable(quorumDidIpfsHash, null); + String quorumWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "didHash", + quorumDidIpfsHash); + + nodeData(quorumDidIpfsHash, quorumWidIpfsHash, ipfs); + } + + for (int i = 0; i < quorumSignatures.length(); i++) { + + JSONObject detailsForVerify = new JSONObject(); + detailsForVerify.put("did", quorumDID.get(i)); + detailsForVerify.put("hash", verifyQuorumHash); + detailsForVerify.put("signature", quorumSignatures.getString(quorumDID.get(i))); + boolean val = Authenticate.verifySignature(detailsForVerify.toString()); + if (val) + quorumSignVerifyCount++; + } + TokenReceiverLogger.debug("Verified Quorum Count " + quorumSignVerifyCount); + yesQuorum = quorumSignVerifyCount >= quorumSignatures.length(); + } + JSONArray wholeTokenChainHash = new JSONArray(); + for (int i = 0; i < intPart; i++) + wholeTokenChainHash.put(wholeTokenChains.getString(i)); + + String hash = calculateHash( + wholeTokens.toString() + wholeTokenChainHash.toString() + partTokens.toString() + + partTokenChainsHash.toString() + receiverDidIpfsHash + senderDidIpfsHash + comment, + "SHA3-256"); + TokenReceiverLogger.debug("Hash to verify Sender: " + hash); + JSONObject detailsForVerify = new JSONObject(); + detailsForVerify.put("did", senderDidIpfsHash); + detailsForVerify.put("hash", hash); + detailsForVerify.put("signature", senderSignature); + + boolean yesSender = Authenticate.verifySignature(detailsForVerify.toString()); + TokenReceiverLogger.debug("Quorum Auth : " + yesQuorum + " Sender Auth : " + yesSender); + if (!(yesSender && yesQuorum)) { + output.println("420"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", tid); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender / Quorum not verified"); + TokenReceiverLogger.info("Sender / Quorum not verified"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + repo(ipfs); + TokenReceiverLogger.debug("Sender and Quorum Verified"); + output.println("200"); + + String pinDetails; + try { + pinDetails = input.readLine(); + } catch (SocketException e) { + TokenReceiverLogger.warn("Sender Stream Null - Pinning Status"); + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender Stream Null - Pinning Status"); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + if (pinDetails.equals("Unpinned")) { + int pinCount = 0; + for (int i = 0; i < intPart; i++) { + + Path tokensPath = Paths.get(TOKENS_PATH + wholeTokens.get(i)); + Files.write(tokensPath, wholeTokenContent.get(i).getBytes()); + add(TOKENS_PATH + wholeTokens.get(i), ipfs); + pin(wholeTokens.get(i).toString(), ipfs); + pinCount++; + + } + + for (int i = 0; i < partTokens.length(); i++) { + File tokenFile = new File(PART_TOKEN_PATH + partTokens.getString(i)); + if (!tokenFile.exists()) + tokenFile.createNewFile(); + + writeToFile(PART_TOKEN_PATH + partTokens.getString(i), partTokenContent.getString(i), false); + String tokenHash = add(PART_TOKEN_PATH + partTokens.getString(i), ipfs); + pin(tokenHash, ipfs); + + } + + if (pinCount == intPart) { + TokenReceiverLogger.debug("Pinned All Tokens"); + output.println("Successfully Pinned"); + + String essentialShare; + try { + essentialShare = input.readLine(); + } catch (SocketException e) { + TokenReceiverLogger.warn("Sender Stream Null - EShare Details"); + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender Stream Null - EShare Details"); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + long endTime = System.currentTimeMillis(); + for (int i = 0; i < intPart; i++) { + String wholeToken = wholeTokens.getString(i); + String hashString = wholeToken.concat(receiverDidIpfsHash); + String hashForPositions = calculateHash(hashString, "SHA3-256"); + + BufferedImage pvt = ImageIO + .read(new File(DATA_PATH.concat(receiverDidIpfsHash).concat("/PrivateShare.png"))); + String firstPrivate = PropImage.img2bin(pvt); + int[] privateIntegerArray1 = strToIntArray(firstPrivate); + String privateBinary = Functions.intArrayToStr(privateIntegerArray1); + String positions = ""; + for (int j = 0; j < privateIntegerArray1.length; j += 49152) { + positions += privateBinary.charAt(j); + } + String ownerIdentity = hashForPositions.concat(positions); + String ownerIdentityHash = calculateHash(ownerIdentity, "SHA3-256"); + + TokenReceiverLogger.debug("Ownership Here"); + TokenReceiverLogger.debug("tokens: " + wholeTokens.getString(i)); + TokenReceiverLogger.debug("hashString: " + hashString); + TokenReceiverLogger.debug("hashForPositions: " + hashForPositions); + TokenReceiverLogger.debug("p1: " + positions); + TokenReceiverLogger.debug("ownerIdentity: " + ownerIdentity); + TokenReceiverLogger.debug("ownerIdentityHash: " + ownerIdentityHash); + + ArrayList groupTokens = new ArrayList<>(); + for (int k = 0; k < intPart; k++) { + if (!wholeTokens.getString(i).equals(wholeTokens.getString(k))) + groupTokens.add(wholeTokens.getString(k)); + } + + JSONArray arrToken = new JSONArray(); + JSONObject objectToken = new JSONObject(); + objectToken.put("tokenHash", wholeTokens.getString(i)); + arrToken.put(objectToken); + JSONArray arr1 = new JSONArray(wholeTokenChainContent.get(i)); + JSONObject obj2 = new JSONObject(); + obj2.put("senderSign", senderSignature); + obj2.put("sender", senderDidIpfsHash); + obj2.put("group", groupTokens); + obj2.put("comment", comment); + obj2.put("tid", tid); + obj2.put("owner", ownerIdentityHash); + arr1.put(obj2); + + writeToFile(TOKENCHAIN_PATH + wholeTokens.getString(i) + ".json", arr1.toString(), false); + + } + + for (int i = 0; i < partTokens.length(); i++) { + JSONObject chequeObject = new JSONObject(); + chequeObject.put("sender", senderDidIpfsHash); + chequeObject.put("receiver", receiverDidIpfsHash); + chequeObject.put("parent-token", partTokens.getString(i)); + chequeObject.put("parent-chain", partTokenChains.getJSONArray(partTokens.getString(i))); + Double partAmount = formatAmount(amountLedger.getDouble(partTokens.getString(i))); + chequeObject.put("amount", partAmount); + chequeObject.put("tid", tid); + + writeToFile(LOGGER_PATH.concat(partTokens.getString(i)), chequeObject.toString(), false); + String chequeHash = IPFSNetwork.add(LOGGER_PATH.concat(partTokens.getString(i)), ipfs); + deleteFile(LOGGER_PATH.concat(partTokens.getString(i))); + + String partsTokens = partTokens.getString(i); + String hashString = partsTokens.concat(receiverDidIpfsHash); + String hashForPositions = calculateHash(hashString, "SHA3-256"); + BufferedImage pvt = ImageIO + .read(new File(DATA_PATH.concat(receiverDidIpfsHash).concat("/PrivateShare.png"))); + String firstPrivate = PropImage.img2bin(pvt); + int[] privateIntegerArray1 = strToIntArray(firstPrivate); + String privateBinary = Functions.intArrayToStr(privateIntegerArray1); + String positions = ""; + for (int j = 0; j < privateIntegerArray1.length; j += 49152) { + positions += privateBinary.charAt(j); + } + + String ownerIdentity = hashForPositions.concat(positions); + String ownerIdentityHash = calculateHash(ownerIdentity, "SHA3-256"); + + TokenReceiverLogger.debug("Ownership Here"); + TokenReceiverLogger.debug("tokens: " + partTokens.getString(i)); + TokenReceiverLogger.debug("hashString: " + hashString); + TokenReceiverLogger.debug("hashForPositions: " + hashForPositions); + TokenReceiverLogger.debug("p1: " + positions); + TokenReceiverLogger.debug("ownerIdentity: " + ownerIdentity); + TokenReceiverLogger.debug("ownerIdentityHash: " + ownerIdentityHash); + + JSONObject newPartObject = new JSONObject(); + newPartObject.put("senderSign", senderSignature); + newPartObject.put("sender", senderDidIpfsHash); + newPartObject.put("receiver", receiverDidIpfsHash); + newPartObject.put("comment", comment); + newPartObject.put("tid", tid); + newPartObject.put("nextHash", ""); + newPartObject.put("owner", ownerIdentityHash); + if (partTokenChainContent.getJSONArray(i).length() == 0) + newPartObject.put("previousHash", ""); + else + newPartObject.put("previousHash", + calculateHash(partTokenChainContent.getJSONArray(i) + .getJSONObject(partTokenChainContent.getJSONArray(i).length() - 1) + .getString("tid"), "SHA3-256")); + + newPartObject.put("amount", partAmount); + newPartObject.put("cheque", chequeHash); + newPartObject.put("role", "Receiver"); + + File chainFile = new File( + PART_TOKEN_CHAIN_PATH.concat(partTokens.getString(i)).concat(".json")); + if (chainFile.exists()) { + + String readChain = readFile(PART_TOKEN_CHAIN_PATH + partTokens.getString(i) + ".json"); + JSONArray readChainArray = new JSONArray(readChain); + readChainArray.put(partTokenChainContent.getJSONArray(i) + .getJSONObject(partTokenChainContent.getJSONArray(i).length() - 1)); + readChainArray.put(newPartObject); + + writeToFile(PART_TOKEN_CHAIN_PATH + partTokens.getString(i) + ".json", + readChainArray.toString(), false); + + } else { + partTokenChainContent.getJSONArray(i).put(newPartObject); + writeToFile(PART_TOKEN_CHAIN_PATH + partTokens.getString(i) + ".json", + partTokenChainContent.getJSONArray(i).toString(), false); + } + } + + JSONObject transactionRecord = new JSONObject(); + transactionRecord.put("role", "Receiver"); + transactionRecord.put("tokens", allTokens); + transactionRecord.put("txn", tid); + transactionRecord.put("quorumList", quorumSignatures.keys()); + transactionRecord.put("senderDID", senderDidIpfsHash); + transactionRecord.put("receiverDID", receiverDidIpfsHash); + transactionRecord.put("Date", getCurrentUtcTime()); + transactionRecord.put("totalTime", (endTime - startTime)); + transactionRecord.put("comment", comment); + transactionRecord.put("essentialShare", essentialShare); + amount = formatAmount(amount); + transactionRecord.put("amount-received", amount); + + JSONArray transactionHistoryEntry = new JSONArray(); + transactionHistoryEntry.put(transactionRecord); + updateJSON("add", WALLET_DATA_PATH + "TransactionHistory.json", + transactionHistoryEntry.toString()); + + for (int i = 0; i < wholeTokens.length(); i++) { + String bankFile = readFile(PAYMENTS_PATH.concat("BNK00.json")); + JSONArray bankArray = new JSONArray(bankFile); + JSONObject tokenObject1 = new JSONObject(); + tokenObject1.put("tokenHash", wholeTokens.getString(i)); + bankArray.put(tokenObject1); + Functions.writeToFile(PAYMENTS_PATH.concat("BNK00.json"), bankArray.toString(), false); + Path tokensPath = Paths.get(TOKENS_PATH + wholeTokens.get(i)); + Files.write(tokensPath, wholeTokenContent.get(i).getBytes()); + } + + String partsFile = readFile(PAYMENTS_PATH.concat("PartsToken.json")); + JSONArray partsReadArray = new JSONArray(partsFile); + + for (int i = 0; i < partTokens.length(); i++) { + boolean writeParts = true; + for (int j = 0; j < partsReadArray.length(); j++) { + if (partsReadArray.getJSONObject(j).getString("tokenHash") + .equals(partTokens.getString(i))) + writeParts = false; + } + if (writeParts) { + JSONObject partObject = new JSONObject(); + partObject.put("tokenHash", partTokens.getString(i)); + partsReadArray.put(partObject); + } + } + writeToFile(PAYMENTS_PATH.concat("PartsToken.json"), partsReadArray.toString(), false); + + TokenReceiverLogger.info("Transaction ID: " + tid + "Transaction Successful"); + output.println("Send Response"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", tid); + APIResponse.put("status", "Success"); + APIResponse.put("tokens", wholeTokens); + APIResponse.put("comment", comment); + APIResponse.put("message", "Transaction Successful"); + TokenReceiverLogger.info(" Transaction Successful"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + output.println("count mistmatch"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "count mismacth"); + TokenReceiverLogger.info(" Transaction failed"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Failed to unpin"); + TokenReceiverLogger.info(" Transaction failed"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Consensus failed at Sender side"); + TokenReceiverLogger.info(" Transaction failed"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } catch (Exception e) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + TokenReceiverLogger.error("Exception Occurred", e); + return APIResponse.toString(); + } finally { + try { + ss.close(); + sk.close(); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + } catch (Exception e) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + TokenReceiverLogger.error("Exception Occurred", e); + } + + } + } } diff --git a/src/com/rubix/TokenTransfer/TokenSender.java b/src/com/rubix/TokenTransfer/TokenSender.java index efc01e02..d5353e3f 100644 --- a/src/com/rubix/TokenTransfer/TokenSender.java +++ b/src/com/rubix/TokenTransfer/TokenSender.java @@ -1,18 +1,50 @@ package com.rubix.TokenTransfer; -import com.rubix.Consensus.InitiatorConsensus; -import com.rubix.Consensus.InitiatorProcedure; -import com.rubix.Resources.Functions; -import com.rubix.Resources.IPFSNetwork; -import io.ipfs.api.IPFS; -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import javax.net.ssl.HttpsURLConnection; -import java.io.*; +import static com.rubix.Resources.Functions.DATA_PATH; +import static com.rubix.Resources.Functions.EXPLORER_IP; +import static com.rubix.Resources.Functions.LOGGER_PATH; +import static com.rubix.Resources.Functions.PAYMENTS_PATH; +import static com.rubix.Resources.Functions.QuorumCheck; +import static com.rubix.Resources.Functions.QuorumSwarmConnect; +import static com.rubix.Resources.Functions.SEND_PORT; +import static com.rubix.Resources.Functions.TOKENCHAIN_PATH; +import static com.rubix.Resources.Functions.TOKENS_PATH; +import static com.rubix.Resources.Functions.WALLET_DATA_PATH; +import static com.rubix.Resources.Functions.calculateHash; +import static com.rubix.Resources.Functions.deleteFile; +import static com.rubix.Resources.Functions.formatAmount; +import static com.rubix.Resources.Functions.getCurrentUtcTime; +import static com.rubix.Resources.Functions.getPeerID; +import static com.rubix.Resources.Functions.getQuorum; +import static com.rubix.Resources.Functions.getSignFromShares; +import static com.rubix.Resources.Functions.getValues; +import static com.rubix.Resources.Functions.minQuorum; +import static com.rubix.Resources.Functions.nodeData; +import static com.rubix.Resources.Functions.partTokenBalance; +import static com.rubix.Resources.Functions.readFile; +import static com.rubix.Resources.Functions.sanityCheck; +import static com.rubix.Resources.Functions.sanityMessage; +import static com.rubix.Resources.Functions.strToIntArray; +import static com.rubix.Resources.Functions.syncDataTable; +import static com.rubix.Resources.Functions.syncDataTableByDID; +import static com.rubix.Resources.Functions.updateJSON; +import static com.rubix.Resources.Functions.updateQuorum; +import static com.rubix.Resources.Functions.writeToFile; +import static com.rubix.Resources.IPFSNetwork.add; +import static com.rubix.Resources.IPFSNetwork.executeIPFSCommands; +import static com.rubix.Resources.IPFSNetwork.forward; +import static com.rubix.Resources.IPFSNetwork.pin; +import static com.rubix.Resources.IPFSNetwork.repo; +import static com.rubix.Resources.IPFSNetwork.swarmConnectP2P; +import static com.rubix.Resources.IPFSNetwork.unpin; + +import java.awt.image.BufferedImage; +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; import java.net.Socket; import java.net.SocketException; import java.net.URL; @@ -23,9 +55,22 @@ import java.util.Iterator; import java.util.List; -import static com.rubix.Resources.Functions.*; -import static com.rubix.Resources.IPFSNetwork.*; +import javax.imageio.ImageIO; +import javax.net.ssl.HttpsURLConnection; +import com.rubix.AuthenticateNode.PropImage; +import com.rubix.Consensus.InitiatorConsensus; +import com.rubix.Consensus.InitiatorProcedure; +import com.rubix.Resources.Functions; +import com.rubix.Resources.IPFSNetwork; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import io.ipfs.api.IPFS; public class TokenSender { private static final Logger TokenSenderLogger = Logger.getLogger(TokenSender.class); @@ -53,20 +98,32 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception JSONObject APIResponse = new JSONObject(); PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); - String receiverPeerId; JSONObject detailsObject = new JSONObject(data); String receiverDidIpfsHash = detailsObject.getString("receiverDidIpfsHash"); + syncDataTableByDID(receiverDidIpfsHash); + String receiverPeerId = getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", receiverDidIpfsHash); String pvt = detailsObject.getString("pvt"); double requestedAmount = detailsObject.getDouble("amount"); int type = detailsObject.getInt("type"); String comment = detailsObject.getString("comment"); APIResponse = new JSONObject(); + int intPart = (int) requestedAmount, wholeAmount; String senderPeerID = getPeerID(DATA_PATH + "DID.json"); TokenSenderLogger.debug("sender peer id" + senderPeerID); String senderDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", senderPeerID); TokenSenderLogger.debug("sender did ipfs hash" + senderDidIpfsHash); + boolean sanityCheck = sanityCheck("Receiver", receiverPeerId, ipfs, port + 10); + if (!sanityCheck) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", sanityMessage); + TokenSenderLogger.warn(sanityMessage); + return APIResponse; + } + if (senderMutex) { APIResponse.put("did", senderDidIpfsHash); APIResponse.put("tid", "null"); @@ -92,9 +149,8 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception writeToFile(partTokensFile.toString(), "[]", false); } - int intPart = (int) requestedAmount, wholeAmount; - TokenSenderLogger.debug("Requested Part: " +requestedAmount); - TokenSenderLogger.debug("Int Part: " +intPart); + TokenSenderLogger.debug("Requested Part: " + requestedAmount); + TokenSenderLogger.debug("Int Part: " + intPart); String bankFile = readFile(PAYMENTS_PATH.concat("BNK00.json")); JSONArray bankArray = new JSONArray(bankFile); JSONArray wholeTokens = new JSONArray(); @@ -107,15 +163,16 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception wholeTokens.put(bankArray.getJSONObject(i).getString("tokenHash")); } - for(int i = 0; i < wholeTokens.length(); i++){ + for (int i = 0; i < wholeTokens.length(); i++) { String tokenRemove = wholeTokens.getString(i); - for(int j = 0; j < bankArray.length(); j++){ - if(bankArray.getJSONObject(j).getString("tokenHash").equals(tokenRemove)) + for (int j = 0; j < bankArray.length(); j++) { + if (bankArray.getJSONObject(j).getString("tokenHash").equals(tokenRemove)) bankArray.remove(j); } } JSONArray wholeTokenChainHash = new JSONArray(); JSONArray tokenPreviousSender = new JSONArray(); + for (int i = 0; i < wholeTokens.length(); i++) { File token = new File(TOKENS_PATH + wholeTokens.get(i)); File tokenchain = new File(TOKENCHAIN_PATH + wholeTokens.get(i) + ".json"); @@ -134,25 +191,32 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception String tokenChainHash = add(TOKENCHAIN_PATH + wholeTokens.get(i) + ".json", ipfs); wholeTokenChainHash.put(tokenChainHash); - String tokenChainFileContent = readFile(TOKENCHAIN_PATH + wholeTokens.get(i) + ".json"); JSONArray tokenChainFileArray = new JSONArray(tokenChainFileContent); JSONArray previousSenderArray = new JSONArray(); - for (int j = 0; j < tokenChainFileArray.length(); j++) { - String peerID = getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", tokenChainFileArray.getJSONObject(j).getString("sender")); - previousSenderArray.put(peerID); + + if (tokenChainFileArray.length() > 0) { + // JSONObject lastObject = + // tokenChainFileArray.getJSONObject(tokenChainFileArray.length() - 1); + + for (int j = 0; j < tokenChainFileArray.length(); j++) { + String peerID = getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", + tokenChainFileArray.getJSONObject(j).getString("sender")); + previousSenderArray.put(peerID); + } } JSONObject previousSenderObject = new JSONObject(); previousSenderObject.put("token", wholeTokenHash); previousSenderObject.put("sender", previousSenderArray); tokenPreviousSender.put(previousSenderObject); + } Double decimalAmount = requestedAmount - wholeAmount; decimalAmount = formatAmount(decimalAmount); - TokenSenderLogger.debug("Decimal Part: " +decimalAmount); + TokenSenderLogger.debug("Decimal Part: " + decimalAmount); boolean newPart = false, oldNew = false; JSONObject amountLedger = new JSONObject(); @@ -172,11 +236,11 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception } else { Double counter = decimalAmount; - JSONArray selectParts = new JSONArray(partContentArray); + JSONArray selectParts = new JSONArray(partFileContent); while (counter > 0.000D) { counter = formatAmount(counter); - TokenSenderLogger.debug("Counter: " + formatAmount(counter) ); - if(!(selectParts.length() == 0)) { + TokenSenderLogger.debug("Counter: " + formatAmount(counter)); + if (!(selectParts.length() == 0)) { TokenSenderLogger.debug("Old Parts"); String currentPartToken = selectParts.getJSONObject(0).getString("tokenHash"); Double currentPartBalance = partTokenBalance(currentPartToken); @@ -189,7 +253,7 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception partTokens.put(currentPartToken); counter -= currentPartBalance; selectParts.remove(0); - }else{ + } else { oldNew = true; TokenSenderLogger.debug("Old Parts then new parts"); String chosenToken = bankArray.getJSONObject(0).getString("tokenHash"); @@ -200,13 +264,13 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception File chainFile = new File(TOKENCHAIN_PATH.concat(chosenToken).concat(".json")); chainFile.renameTo(new File(PART_TOKEN_CHAIN_PATH.concat(chosenToken).concat(".json"))); - File shiftedFile = new File(PAYMENTS_PATH.concat("ShiftedTokens.json")); if (!shiftedFile.exists()) { shiftedFile.createNewFile(); JSONArray shiftedTokensArray = new JSONArray(); shiftedTokensArray.put(chosenToken); - writeToFile(PAYMENTS_PATH.concat("ShiftedTokens.json"), shiftedTokensArray.toString(), false); + writeToFile(PAYMENTS_PATH.concat("ShiftedTokens.json"), shiftedTokensArray.toString(), + false); } else { String shiftedContent = readFile(PAYMENTS_PATH.concat("ShiftedTokens.json")); JSONArray shiftedArray = new JSONArray(shiftedContent); @@ -219,11 +283,10 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception } } String tokenChainPath = "", tokenPath = ""; - if(newPart) { + if (newPart) { tokenChainPath = TOKENCHAIN_PATH; tokenPath = TOKENS_PATH; - } - else{ + } else { tokenChainPath = TOKENCHAIN_PATH.concat("PARTS/"); tokenPath = TOKENS_PATH.concat("PARTS/"); } @@ -251,7 +314,6 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception String hash = add(tokenPath + partTokens.getString(i), ipfs); pin(hash, ipfs); - String chainContent = readFile(tokenChainPath.concat(partTokens.getString(i)).concat(".json")); JSONArray chainArray = new JSONArray(); JSONArray finalChainArray = new JSONArray(chainContent); @@ -263,13 +325,17 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception } else if (finalChainArray.length() > 1) { if (j == 0) { object.put("previousHash", ""); - object.put("nextHash", calculateHash(finalChainArray.getJSONObject(j + 1).getString("tid"), "SHA3-256")); + object.put("nextHash", + calculateHash(finalChainArray.getJSONObject(j + 1).getString("tid"), "SHA3-256")); } else if (j == finalChainArray.length() - 1) { - object.put("previousHash", calculateHash(finalChainArray.getJSONObject(j - 1).getString("tid"), "SHA3-256")); + object.put("previousHash", + calculateHash(finalChainArray.getJSONObject(j - 1).getString("tid"), "SHA3-256")); object.put("nextHash", ""); } else { - object.put("previousHash", calculateHash(finalChainArray.getJSONObject(j - 1).getString("tid"), "SHA3-256")); - object.put("nextHash", calculateHash(finalChainArray.getJSONObject(j + 1).getString("tid"), "SHA3-256")); + object.put("previousHash", + calculateHash(finalChainArray.getJSONObject(j - 1).getString("tid"), "SHA3-256")); + object.put("nextHash", + calculateHash(finalChainArray.getJSONObject(j + 1).getString("tid"), "SHA3-256")); } } chainArray.put(object); @@ -280,24 +346,48 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception partTokenChainHash.put(add(tokenChainPath.concat(partTokens.getString(i)).concat(".json"), ipfs)); } - String authSenderByRecHash = calculateHash(wholeTokens.toString() + wholeTokenChainHash.toString() + partTokens.toString() + partTokenChainHash.toString() + receiverDidIpfsHash + senderDidIpfsHash + comment, "SHA3-256"); + String authSenderByRecHash = calculateHash( + wholeTokens.toString() + wholeTokenChainHash.toString() + partTokens.toString() + + partTokenChainHash.toString() + receiverDidIpfsHash + senderDidIpfsHash + comment, + "SHA3-256"); TokenSenderLogger.debug("Hash to verify Sender: " + authSenderByRecHash); String tid = calculateHash(authSenderByRecHash, "SHA3-256"); TokenSenderLogger.debug("Sender by Receiver Hash " + authSenderByRecHash); TokenSenderLogger.debug("TID on sender " + tid); + JSONArray allTokens = new JSONArray(); + for (int i = 0; i < wholeTokens.length(); i++) + allTokens.put(wholeTokens.getString(i)); + for (int i = 0; i < partTokens.length(); i++) + allTokens.put(partTokens.getString(i)); + + JSONArray positionsArray = new JSONArray(); + for (int i = 0; i < allTokens.length(); i++) { + String tokens = allTokens.getString(i); + String hashString = tokens.concat(senderDidIpfsHash); + String hashForPositions = calculateHash(hashString, "SHA3-256"); + BufferedImage privateShare = ImageIO + .read(new File(DATA_PATH.concat(senderDidIpfsHash).concat("/PrivateShare.png"))); + String firstPrivate = PropImage.img2bin(privateShare); + int[] privateIntegerArray1 = strToIntArray(firstPrivate); + String privateBinary = Functions.intArrayToStr(privateIntegerArray1); + String positions = ""; + for (int j = 0; j < privateIntegerArray1.length; j += 49152) { + positions += privateBinary.charAt(j); + } + positionsArray.put(positions); + + TokenSenderLogger.debug("Ownership Here Sender Calculation"); + TokenSenderLogger.debug("tokens: " + tokens); + TokenSenderLogger.debug("hashString: " + hashString); + TokenSenderLogger.debug("hashForPositions: " + hashForPositions); + TokenSenderLogger.debug("p1: " + positions); + } - JSONArray quorumArray; JSONArray alphaQuorum = new JSONArray(); JSONArray betaQuorum = new JSONArray(); - JSONArray gammaQuorum = new JSONArray(); - int alphaSize; - - ArrayList alphaPeersList; - ArrayList betaPeersList; - ArrayList gammaPeersList; - - long startTime = System.currentTimeMillis(); + JSONArray gammaQuorum = new JSONArray(); + JSONArray quorumArray = new JSONArray(); switch (type) { case 1: { writeToFile(LOGGER_PATH + "tempbeta", tid.concat(senderDidIpfsHash), false); @@ -308,7 +398,8 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception String gammaHash = IPFSNetwork.add(LOGGER_PATH + "tempgamma", ipfs); deleteFile(LOGGER_PATH + "tempgamma"); - quorumArray = getQuorum(betaHash, gammaHash, senderDidIpfsHash, receiverDidIpfsHash, wholeTokens.length()); + quorumArray = getQuorum(senderDidIpfsHash, receiverDidIpfsHash, + allTokens.length()); break; } @@ -328,19 +419,69 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception } } + int alphaSize; - TokenSenderLogger.debug("1"); - TokenSenderLogger.debug("Whole tokens: " + wholeTokens); - TokenSenderLogger.debug("Part tokens: " + partTokens); - long endTime = System.currentTimeMillis(); - long totalTime = endTime - startTime; - eventLogger.debug("Get Quorum List " + totalTime); + ArrayList alphaPeersList; + ArrayList betaPeersList; + ArrayList gammaPeersList; + + List quorumList = new ArrayList<>(); + String errMessage = null; + for (int i = 0; i < quorumArray.length(); i++) { + + if(quorumArray.get(i).equals(senderDidIpfsHash)) { + TokenSenderLogger.error("SenderDID "+senderDidIpfsHash+" cannot be a Quorum"); + errMessage = "SenderDID "+senderDidIpfsHash; + } + if(quorumArray.get(i).equals(receiverDidIpfsHash)) { + TokenSenderLogger.error("ReceiverDID "+receiverDidIpfsHash+" cannot be a Quorum"); + if(errMessage != null) { + errMessage = errMessage+" and "; + } + errMessage = "ReceiverDID "+receiverDidIpfsHash; + } + if(errMessage != null) { + APIResponse.put("status", "Failed"); + APIResponse.put("message", errMessage+" cannot be a Quorum "); + return APIResponse; + } + + } + + TokenSenderLogger.debug("Updated quorumlist is "+quorumArray.toString()); + + //sanity check for Quorum - starts + int alphaCheck = 0, betaCheck = 0, gammaCheck = 0; + JSONArray sanityFailedQuorum = new JSONArray(); + for (int i = 0; i < quorumArray.length(); i++) { + String quorumPeerID = getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", + quorumArray.getString(i)); + boolean quorumSanityCheck = sanityCheck("Quorum",quorumPeerID, ipfs, port + 11); + + if (!quorumSanityCheck) { + sanityFailedQuorum.put(quorumPeerID); + if (i <= 6) + alphaCheck++; + if (i >= 7 && i <= 13) + betaCheck++; + if (i >= 14 && i <= 20) + gammaCheck++; + } + } + + if (alphaCheck > 2 || betaCheck > 2 || gammaCheck > 2) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + String message = "Quorum: ".concat(sanityFailedQuorum.toString()).concat(" "); + APIResponse.put("message", message.concat(sanityMessage)); + TokenSenderLogger.warn("Quorum: ".concat(message.concat(sanityMessage))); + return APIResponse; + } + //sanity check for Quorum - Ends + long startTime, endTime, totalTime; - startTime = System.currentTimeMillis(); QuorumSwarmConnect(quorumArray, ipfs); - endTime = System.currentTimeMillis(); - totalTime = endTime - startTime; - eventLogger.debug("Swarm Connect " + totalTime); alphaSize = quorumArray.length() - 14; @@ -372,9 +513,9 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception return APIResponse; } - syncDataTable(receiverDidIpfsHash, null); - receiverPeerId = getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", receiverDidIpfsHash); + // receiverPeerId = getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", + // receiverDidIpfsHash); if (!receiverPeerId.equals("")) { TokenSenderLogger.debug("Swarm connecting to " + receiverPeerId); @@ -390,7 +531,8 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception return APIResponse; } - String receiverWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "didHash", receiverDidIpfsHash); + String receiverWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "didHash", + receiverDidIpfsHash); if (!receiverWidIpfsHash.equals("")) { nodeData(receiverDidIpfsHash, receiverWidIpfsHash, ipfs); } else { @@ -438,9 +580,22 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception return APIResponse; } + + if (peerAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + TokenSenderLogger.info("Receiver is unable to authenticate the sender!"); + output.close(); + input.close(); + senderSocket.close(); + senderMutex = false; + updateQuorum(quorumArray, null, false, type); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", tid); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver is unable to authenticate the sender!"); + return APIResponse; - - if (peerAuth != null && (!peerAuth.equals("200"))) { + }else if (peerAuth != null && (!peerAuth.equals("200"))) { executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); TokenSenderLogger.info("Sender Data Not Available"); output.close(); @@ -455,12 +610,13 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception return APIResponse; } - + String senderSign = getSignFromShares(pvt, authSenderByRecHash); JSONObject senderDetails2Receiver = new JSONObject(); senderDetails2Receiver.put("sign", senderSign); senderDetails2Receiver.put("tid", tid); senderDetails2Receiver.put("comment", comment); + JSONObject partTokenChainArrays = new JSONObject(); for (int i = 0; i < partTokens.length(); i++) { String chainContent = readFile(tokenChainPath.concat(partTokens.getString(i)).concat(".json")); @@ -472,7 +628,8 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception } else { JSONObject secondLastObject = chainArray.getJSONObject(chainArray.length() - 1); secondLastObject.put("nextHash", calculateHash(tid, "SHA3-256")); - newLastObject.put("previousHash", calculateHash(chainArray.getJSONObject(chainArray.length() - 1).getString("tid"), "SHA3-256")); + newLastObject.put("previousHash", + calculateHash(chainArray.getJSONObject(chainArray.length() - 1).getString("tid"), "SHA3-256")); } Double amount = formatAmount(amountLedger.getDouble(partTokens.getString(i))); @@ -489,7 +646,7 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception partTokenChainArrays.put(partTokens.getString(i), chainArray); } - + JSONObject tokenDetails = new JSONObject(); tokenDetails.put("whole-tokens", wholeTokens); tokenDetails.put("whole-tokenChains", wholeTokenChainHash); @@ -498,31 +655,39 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception tokenDetails.put("part-tokenChains", partTokenChainArrays); tokenDetails.put("sender", senderDidIpfsHash); String doubleSpendString = tokenDetails.toString(); - + String doubleSpend = calculateHash(doubleSpendString, "SHA3-256"); writeToFile(LOGGER_PATH + "doubleSpend", doubleSpend, false); TokenSenderLogger.debug("********Double Spend Hash*********: " + doubleSpend); IPFSNetwork.addHashOnly(LOGGER_PATH + "doubleSpend", ipfs); deleteFile(LOGGER_PATH + "doubleSpend"); - - + JSONObject tokenObject = new JSONObject(); tokenObject.put("tokenDetails", tokenDetails); tokenObject.put("previousSender", tokenPreviousSender); + tokenObject.put("positions", positionsArray); tokenObject.put("amount", requestedAmount); tokenObject.put("amountLedger", amountLedger); - - - - /** - * Sending Token Details to Receiver - * Receiver to authenticate Tokens (Double Spending, IPFS availability) - */ - output.println(tokenObject); + + if(Functions.multiplePinCheck(senderDidIpfsHash, tokenObject, ipfs) == 420) { + APIResponse.put("message", "Multiple Owners Found. Kindly re-initiate transaction"); + return APIResponse; + }else { + TokenSenderLogger.debug("No Multiple Pins found, initating transcation"); + } + + + /** + * Sending Token Details to Receiver + * Receiver to authenticate Tokens (Double Spending, IPFS availability) + */ + output.println(tokenObject); + String tokenAuth; try { tokenAuth = input.readLine(); + TokenSenderLogger.debug("Token Auth Code: " + tokenAuth); } catch (SocketException e) { TokenSenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Token Auth"); executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); @@ -538,70 +703,63 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception return APIResponse; } - if (tokenAuth != null && (!tokenAuth.equals("200"))) { + if(tokenAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + TokenSenderLogger.info("Receiver is unable to verify the tokens!"); + output.close(); + input.close(); + senderSocket.close(); + senderMutex = false; + updateQuorum(quorumArray, null, false, type); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", tid); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver is unable to verify the tokens!"); + return APIResponse; + }else if (tokenAuth != null && (tokenAuth.startsWith("4"))) { switch (tokenAuth) { case "420": String doubleSpent = input.readLine(); String owners = input.readLine(); JSONArray ownersArray = new JSONArray(owners); TokenSenderLogger.info("Multiple Owners for " + doubleSpent); - APIResponse.put("message", "Multiple Owners for " + doubleSpent); - APIResponse.put("Owners", ownersArray); - removeToken(); + TokenSenderLogger.info("Owners " + ownersArray); + TokenSenderLogger.info("Kindly re-initiate transaction"); + APIResponse.put("message", "Multiple Owners for " + doubleSpent + " Owners: " + ownersArray + + ". Kindly re-initiate transaction"); break; case "421": - TokenSenderLogger.info("Consensus ID not unique"); - APIResponse.put("message", "Consensus ID not unique"); - removeToken(); + TokenSenderLogger.info("Consensus ID not unique. Kindly re-initiate transaction"); + APIResponse.put("message", "Consensus ID not unique. Kindly re-initiate transaction"); break; case "422": - TokenSenderLogger.info("Tokens Not Verified"); - APIResponse.put("message", "Tokens Not Verified"); - removeToken(); + TokenSenderLogger.info("Tokens Not Verified. Kindly re-initiate transaction"); + APIResponse.put("message", "Tokens Not Verified. Kindly re-initiate transaction"); break; case "423": - TokenSenderLogger.info("Broken Cheque Chain"); - APIResponse.put("message", "Broken Cheque Chain"); + TokenSenderLogger.info("Broken Cheque Chain. Kindly re-initiate transaction"); + APIResponse.put("message", "Broken Cheque Chain. Kindly re-initiate transaction"); break; case "424": - TokenSenderLogger.info("Token wholly spent already"); - APIResponse.put("message", "Token wholly spent already"); + String invalidTokens = input.readLine(); + JSONArray tokensArray = new JSONArray(invalidTokens); + TokenSenderLogger.info("Ownership Check Failed for " + tokensArray); + APIResponse.put("message", "Ownership Check Failed"); break; - } - executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); - - output.close(); - input.close(); - senderSocket.close(); - senderMutex = false; + case "425": + TokenSenderLogger.info("Token wholly spent already. Kindly re-initiate transaction"); + APIResponse.put("message", "Token wholly spent already. Kindly re-initiate transaction"); + break; - updateQuorum(quorumArray, null, false, type); - APIResponse.put("did", senderDidIpfsHash); - APIResponse.put("tid", tid); - APIResponse.put("status", "Failed"); - return APIResponse; - } + case "426": + TokenSenderLogger.info("Contains Invalid Tokens. Kindly check tokens in your wallet"); + APIResponse.put("message", + "Contains Invalid Tokens. Kindly check tokens in your wallet"); + break; - JSONObject dataObject = new JSONObject(); - dataObject.put("tid", tid); - dataObject.put("message", doubleSpendString); - dataObject.put("receiverDidIpfs", receiverDidIpfsHash); - dataObject.put("pvt", pvt); - dataObject.put("senderDidIpfs", senderDidIpfsHash); - dataObject.put("token", wholeTokens.toString()); - dataObject.put("alphaList", alphaPeersList); - dataObject.put("betaList", betaPeersList); - dataObject.put("gammaList", gammaPeersList); - - - InitiatorProcedure.consensusSetUp(dataObject.toString(), ipfs, SEND_PORT + 100, alphaSize, ""); - TokenSenderLogger.debug("length on sender " + InitiatorConsensus.quorumSignature.length() + "response count " + InitiatorConsensus.quorumResponse); - if (InitiatorConsensus.quorumSignature.length() < (minQuorum(alphaSize) + 2 * minQuorum(7))) { - TokenSenderLogger.debug("Consensus Failed"); - senderDetails2Receiver.put("status", "Consensus Failed"); - output.println(senderDetails2Receiver); + } executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); output.close(); input.close(); @@ -611,17 +769,48 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception APIResponse.put("did", senderDidIpfsHash); APIResponse.put("tid", tid); APIResponse.put("status", "Failed"); - APIResponse.put("message", "Transaction declined by Quorum"); return APIResponse; - } - - TokenSenderLogger.debug("Consensus Reached"); - senderDetails2Receiver.put("status", "Consensus Reached"); - senderDetails2Receiver.put("quorumsign", InitiatorConsensus.quorumSignature.toString()); - - output.println(senderDetails2Receiver); - TokenSenderLogger.debug("Quorum Signatures length " + InitiatorConsensus.quorumSignature.length()); + + TokenSenderLogger.debug("Token Auth Code: " + tokenAuth); + + JSONObject dataObject = new JSONObject(); + dataObject.put("tid", tid); + dataObject.put("message", doubleSpendString); + dataObject.put("receiverDidIpfs", receiverDidIpfsHash); + dataObject.put("pvt", pvt); + dataObject.put("senderDidIpfs", senderDidIpfsHash); + dataObject.put("token", wholeTokens.toString()); + dataObject.put("alphaList", alphaPeersList); + dataObject.put("betaList", betaPeersList); + dataObject.put("gammaList", gammaPeersList); + + InitiatorProcedure.consensusSetUp(dataObject.toString(), ipfs, SEND_PORT + 100, alphaSize, ""); + + if (InitiatorConsensus.quorumSignature.length() < (minQuorum(alphaSize) + 2 * minQuorum(7))) { + TokenSenderLogger.debug("Consensus Failed"); + senderDetails2Receiver.put("status", "Consensus Failed"); + output.println(senderDetails2Receiver); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + output.close(); + input.close(); + senderSocket.close(); + senderMutex = false; + updateQuorum(quorumArray, null, false, type); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", tid); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Transaction declined by Quorum"); + return APIResponse; + + } + + TokenSenderLogger.debug("Consensus Reached"); + senderDetails2Receiver.put("status", "Consensus Reached"); + senderDetails2Receiver.put("quorumsign", InitiatorConsensus.quorumSignature.toString()); + + output.println(senderDetails2Receiver); + TokenSenderLogger.debug("Quorum Signatures length " + InitiatorConsensus.quorumSignature.length()); String signatureAuth; try { @@ -644,9 +833,9 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception TokenSenderLogger.info("signatureAuth : " + signatureAuth); endTime = System.currentTimeMillis(); totalTime = endTime - startTime; - if (signatureAuth != null && (!signatureAuth.equals("200"))) { + if (signatureAuth == null) { executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); - TokenSenderLogger.info("Authentication Failed"); + TokenSenderLogger.info("Receiver is unable to authenticate Sender!"); output.close(); input.close(); senderSocket.close(); @@ -655,18 +844,29 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception APIResponse.put("did", senderDidIpfsHash); APIResponse.put("tid", tid); APIResponse.put("status", "Failed"); - APIResponse.put("message", "Sender not authenticated"); + APIResponse.put("message", "Receiver is unable to authenticate Sender!"); return APIResponse; } + else if (signatureAuth != null && (!signatureAuth.equals("200"))) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + TokenSenderLogger.info("Authentication Failed!"); + output.close(); + input.close(); + senderSocket.close(); + senderMutex = false; + updateQuorum(quorumArray, null, false, type); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", tid); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender not authenticated"); + return APIResponse; - for (int i = 0; i < wholeTokens.length(); i++) - unpin(String.valueOf(wholeTokens.get(i)), ipfs); - repo(ipfs); - - + } TokenSenderLogger.debug("Unpinned Tokens"); output.println("Unpinned"); + + String confirmation; try { confirmation = input.readLine(); @@ -685,7 +885,21 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception return APIResponse; } - if (confirmation != null && (!confirmation.equals("Successfully Pinned"))) { + if (confirmation == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + TokenSenderLogger.info("Receiver is unable to Pin the tokens!"); + output.close(); + input.close(); + senderSocket.close(); + senderMutex = false; + updateQuorum(quorumArray, null, false, type); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", tid); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver is unable to Pin the tokens!"); + return APIResponse; + + }else if (confirmation != null && (!confirmation.equals("Successfully Pinned"))) { TokenSenderLogger.warn("Multiple Owners for the token"); executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); TokenSenderLogger.info("Tokens with multiple pins"); @@ -701,10 +915,13 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception return APIResponse; } - TokenSenderLogger.debug("3"); + + TokenSenderLogger.debug("3"); TokenSenderLogger.debug("Whole tokens: " + wholeTokens); TokenSenderLogger.debug("Part tokens: " + partTokens); output.println(InitiatorProcedure.essential); + + String respAuth; try { respAuth = input.readLine(); @@ -719,13 +936,27 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception APIResponse.put("did", senderDidIpfsHash); APIResponse.put("tid", "null"); APIResponse.put("status", "Failed"); - APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "is unable to respond! - Share Confirmation"); + APIResponse.put("message", + "Receiver " + receiverDidIpfsHash + "is unable to respond! - Share Confirmation"); return APIResponse; } - - if (respAuth != null && (!respAuth.equals("Send Response"))) { - + if(respAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + TokenSenderLogger.info("Receiver is unable to complete the transaction!"); + output.close(); + input.close(); + senderSocket.close(); + senderMutex = false; + updateQuorum(quorumArray, null, false, type); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", tid); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver is unable to complete the transaction!"); + return APIResponse; + + + }else if (respAuth != null && (!respAuth.equals("Send Response"))) { executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); output.close(); input.close(); @@ -738,10 +969,14 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception APIResponse.put("message", "Receiver process not over"); TokenSenderLogger.info("Incomplete Transaction"); return APIResponse; - } - - TokenSenderLogger.debug("Operation over"); + + TokenSenderLogger.debug("Operation over"); + + for (int i = 0; i < wholeTokens.length(); i++) + unpin(String.valueOf(wholeTokens.get(i)), ipfs); + repo(ipfs); + Iterator keys = InitiatorConsensus.quorumSignature.keys(); JSONArray signedQuorumList = new JSONArray(); while (keys.hasNext()) @@ -753,21 +988,8 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception APIResponse.put("quorumlist", signedQuorumList); APIResponse.put("receiver", receiverDidIpfsHash); APIResponse.put("totaltime", totalTime); - - updateQuorum(quorumArray, signedQuorumList, true, type); - - - JSONArray allTokens = new JSONArray(); - for(int i = 0; i < wholeTokens.length(); i++) - allTokens.put(wholeTokens.getString(i)); - for(int i = 0; i < partTokens.length(); i++) - allTokens.put(partTokens.getString(i)); - - TokenSenderLogger.debug("4"); - TokenSenderLogger.debug("All tokens: " + allTokens); - TokenSenderLogger.debug("Whole tokens: " + wholeTokens); - TokenSenderLogger.debug("Part tokens: " + partTokens); - + + JSONObject transactionRecord = new JSONObject(); transactionRecord.put("role", "Sender"); transactionRecord.put("tokens", allTokens); @@ -782,16 +1004,13 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception requestedAmount = formatAmount(requestedAmount); transactionRecord.put("amount-spent", requestedAmount); - JSONArray transactionHistoryEntry = new JSONArray(); transactionHistoryEntry.put(transactionRecord); updateJSON("add", WALLET_DATA_PATH + "TransactionHistory.json", transactionHistoryEntry.toString()); - for (int i = 0; i < wholeTokens.length(); i++) - Files.deleteIfExists(Paths.get(tokenPath + wholeTokens.get(i))); - for (int i = 0; i < wholeTokens.length(); i++) { + deleteFile(TOKENS_PATH.concat(wholeTokens.getString(i))); Functions.updateJSON("remove", PAYMENTS_PATH.concat("BNK00.json"), wholeTokens.getString(i)); } @@ -818,7 +1037,8 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception } else { JSONObject secondLastObject = chainArray.getJSONObject(chainArray.length() - 1); secondLastObject.put("nextHash", calculateHash(tid, "SHA3-256")); - newLastObject.put("previousHash", calculateHash(chainArray.getJSONObject(chainArray.length() - 1).getString("tid"), "SHA3-256")); + newLastObject.put("previousHash", + calculateHash(chainArray.getJSONObject(chainArray.length() - 1).getString("tid"), "SHA3-256")); } Double amount = formatAmount(decimalAmount); @@ -839,7 +1059,6 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception File chainFile = new File(TOKENCHAIN_PATH.concat(partTokens.getString(0)).concat(".json")); chainFile.renameTo(new File(PART_TOKEN_CHAIN_PATH.concat(partTokens.getString(0)).concat(".json"))); - File shiftedFile = new File(PAYMENTS_PATH.concat("ShiftedTokens.json")); if (!shiftedFile.exists()) { shiftedFile.createNewFile(); @@ -865,10 +1084,12 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception } else { JSONObject secondLastObject = chainArray.getJSONObject(chainArray.length() - 1); secondLastObject.put("nextHash", calculateHash(tid, "SHA3-256")); - newLastObject.put("previousHash", calculateHash(chainArray.getJSONObject(chainArray.length() - 1).getString("tid"), "SHA3-256")); + newLastObject.put("previousHash", calculateHash( + chainArray.getJSONObject(chainArray.length() - 1).getString("tid"), "SHA3-256")); } - TokenSenderLogger.debug("Amount from ledger: " + formatAmount(amountLedger.getDouble(partTokens.getString(i)))); + TokenSenderLogger + .debug("Amount from ledger: " + formatAmount(amountLedger.getDouble(partTokens.getString(i)))); Double amount = formatAmount(amountLedger.getDouble(partTokens.getString(i))); newLastObject.put("senderSign", senderSign); @@ -880,7 +1101,8 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception newLastObject.put("role", "Sender"); newLastObject.put("amount", amount); chainArray.put(newLastObject); - writeToFile(TOKENCHAIN_PATH.concat("PARTS/").concat(partTokens.getString(i)).concat(".json"), chainArray.toString(), false); + writeToFile(TOKENCHAIN_PATH.concat("PARTS/").concat(partTokens.getString(i)).concat(".json"), + chainArray.toString(), false); TokenSenderLogger.debug("Checking Parts Token Balance ..."); Double availableParts = partTokenBalance(partTokens.getString(i)); @@ -897,12 +1119,12 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception deleteFile(PART_TOKEN_PATH.concat(partTokens.getString(i))); } } - if(oldNew){ - String token = partTokens.getString(partTokens.length()-1); + if (oldNew) { + String token = partTokens.getString(partTokens.length() - 1); String bnk = readFile(PAYMENTS_PATH.concat("BNK00.json")); JSONArray bnkArray = new JSONArray(bnk); - for(int i = 0; i < bnkArray.length(); i++){ - if(bnkArray.getJSONObject(i).getString("tokenHash").equals(token)) + for (int i = 0; i < bnkArray.length(); i++) { + if (bnkArray.getJSONObject(i).getString("tokenHash").equals(token)) bnkArray.remove(i); } writeToFile(PAYMENTS_PATH.concat("BNK00.json"), bnkArray.toString(), false); @@ -915,7 +1137,16 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception } } - //Populating data to explorer + TokenSenderLogger.info("Transaction Successful"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + updateQuorum(quorumArray, signedQuorumList, true, type); + output.close(); + input.close(); + senderSocket.close(); + senderMutex = false; + + + // Populating data to explorer if (!EXPLORER_IP.contains("127.0.0.1")) { List tokenList = new ArrayList<>(); @@ -970,14 +1201,6 @@ public static JSONObject Send(String data, IPFS ipfs, int port) throws Exception TokenSenderLogger.debug(response.toString()); } - - - TokenSenderLogger.info("Transaction Successful"); - executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); - output.close(); - input.close(); - senderSocket.close(); - senderMutex = false; return APIResponse; }