diff --git a/src/Fork/ForkResolution.java b/src/Fork/ForkResolution.java new file mode 100644 index 00000000..595ce6e5 --- /dev/null +++ b/src/Fork/ForkResolution.java @@ -0,0 +1,240 @@ +package Fork; + +import com.rubix.Ping.VerifyStakedToken; +import com.rubix.Resources.IPFSNetwork; +import org.apache.log4j.Logger; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.ArrayList; + +import static com.rubix.Resources.Functions.*; + +public class ForkResolution { + public static Logger ForkResolutionLogger = Logger.getLogger(ForkResolution.class); + public static String resolutionMessage; + public static ArrayList pinOwnersArrayTransferToken = new ArrayList(); + public static ArrayList pinOwnersArrayPledgedToken = new ArrayList(); + + public static boolean check(JSONObject tokenDetails) throws IOException, InterruptedException, JSONException { + /** + * 1. Check number of pins on the token + * 2. If number of pins < 2 - Pass the token + * 3. Else check if the token has any tokens pledged for it + * 4. If Pledged - Check the number of pins on that token + * 5. Else reject the transfer token + * 6. If number of pins on the pledged token == 1 - Pass the transfer token + * 7. Else Reject the transfer token + * 8. Check if the transfer token is a recently unpledged token + * 9. If it is - Contact the node owning token [Ct] it pledged for and ask for the tokenchain height + * 10.Make sure Ct has genuine pins or match the height of the pledging + */ + + boolean resolution = true; + +// ForkResolutionLogger.debug("Token Details:" + tokenDetails); + + ArrayList previousSender = new ArrayList(); + JSONArray ownersReceived = new JSONArray(); + + JSONArray previousSendersArray = tokenDetails.getJSONArray("previousSendersArray"); + String token = tokenDetails.getString("token"); + JSONArray tokenChain = tokenDetails.getJSONArray("tokenChain"); + String currentSender = tokenDetails.get("currentSender").toString(); + String currentReceiver = tokenDetails.get("currentReceiver").toString(); + + ForkResolutionLogger.debug("Unpledged Token Check: " + token); + boolean tokenOwners = true; + + ForkResolutionLogger.debug("Checking owners for " + token + " Please wait..."); + pinOwnersArrayTransferToken = IPFSNetwork.dhtOwnerCheck(token); + ForkResolutionLogger.debug("Providers for " + token + " is "+pinOwnersArrayTransferToken.toString()); + + //TODO remove current sender and receiver from the list + JSONArray removerCurrentProvidersArray = new JSONArray(); + for(int i =0; i < pinOwnersArrayTransferToken.size(); i++) { + if(!(pinOwnersArrayTransferToken.get(i).toString().equals(currentReceiver) || pinOwnersArrayTransferToken.get(i).toString().equals(currentSender))) + removerCurrentProvidersArray.put(pinOwnersArrayTransferToken.get(i).toString()); + } + + ForkResolutionLogger.debug("Providers for " + token + " after cleanup is "+removerCurrentProvidersArray.toString()); + + + pinOwnersArrayTransferToken = new ArrayList(); + for(int i=0; i 0) { + ForkResolutionLogger.debug("Multiple pins found"); + for (int j = 0; j < previousSendersArray.length(); j++) { + if (previousSendersArray.getJSONObject(j).getString("token").equals(token)) + ownersReceived = previousSendersArray.getJSONObject(j).getJSONArray("sender"); + } + + for (int j = 0; j < ownersReceived.length(); j++) { + previousSender.add(ownersReceived.getString(j)); + } + + for (int j = 0; j < pinOwnersArrayTransferToken.size(); j++) { + if (!previousSender.contains(pinOwnersArrayTransferToken.get(j).toString())) { + ForkResolutionLogger.debug("Multiple pins of " + pinOwnersArrayTransferToken.get(j).toString() + " not contained in history"); + tokenOwners = false; + }else{ + ForkResolutionLogger.debug("Multiple pins of " + pinOwnersArrayTransferToken.get(j).toString() + " contained in history"); + } + } + } else { + ForkResolutionLogger.debug("Token " + token + " has not multiple pins. Passed !!!"); + } + + + ForkResolutionLogger.debug("Tokenowner status " + tokenOwners ); + + + if (!tokenOwners) { + ForkResolutionLogger.debug("Multiple pins found for token " + token + ". Checking for pledged details "); + + JSONObject lastObject = tokenChain.getJSONObject(tokenChain.length() - 1); +// ForkResolutionLogger.debug("Last Object of token " + token + ": " + lastObject); + if (lastObject.has("tokensPledgedWith")) { + if (lastObject.getJSONArray("tokensPledgedWith") != null) { + JSONArray pledgeTokens = lastObject.getJSONArray("tokensPledgedWith"); + for (int i = 0; i < pledgeTokens.length(); i++) { + ForkResolutionLogger.debug("Checking owners for pledgeToken" + pledgeTokens.getString(i) + " Please wait..."); + pinOwnersArrayPledgedToken = IPFSNetwork.dhtOwnerCheck(pledgeTokens.getString(i)); + if (pinOwnersArrayPledgedToken.size() != 1) { + resolution = false; + resolutionMessage = "Pledge token has more than one owner"; + } else { + ForkResolutionLogger.debug("Pledged Token " + pledgeTokens.getString(i) + " has not multiple pins. Passed !!!"); + return true; + } + } + } + } else { + resolution = false; + resolutionMessage = "Transfer token has more owner and no token pledged for"; + } + } + + return resolution; + + } + + public static boolean verifyUnpledgedToken(String transferToken, String pledgedToken, String currentSender, String currentReceiver) throws IOException, InterruptedException, JSONException { + ForkResolutionLogger.debug("Pledged Token Check: " + transferToken); + + ArrayList pinListTransferToken = IPFSNetwork.dhtOwnerCheck(transferToken); + JSONArray removerCurrentProvidersArray = new JSONArray(); + for(int i =0; i < pinListTransferToken.size(); i++) { + if(!(pinListTransferToken.get(i).toString().equals(currentReceiver) || pinListTransferToken.get(i).toString().equals(currentSender))) + removerCurrentProvidersArray.put(pinListTransferToken.get(i).toString()); + } + + pinListTransferToken = new ArrayList(); + for(int i=0; i 2) { + ForkResolutionLogger.debug("Transfer token " + transferToken + " has multiple pins. Checking pledged details"); + ArrayList pinListPledgeToken = IPFSNetwork.dhtOwnerCheck(pledgedToken); + if (pinListPledgeToken.size() > 1) { + ForkResolutionLogger.debug("Pledged token has multiple pins. Verifying token chain height details"); + JSONArray tokenChainsList = new JSONArray(); + for (int i = 0; i < pinListPledgeToken.size(); i++) { + boolean listStatus = VerifyStakedToken.Contact(pinListPledgeToken.get(i).toString(), SEND_PORT + 16, pledgedToken, "", "Get-TokenChain"); + if (listStatus) { + JSONObject chainObject = new JSONObject(); + chainObject.put("node", pinListPledgeToken.get(i).toString()); + chainObject.put("chain", VerifyStakedToken.tokenChain); + chainObject.put("hash", calculateHash(VerifyStakedToken.tokenChain.toString(), "SHA3-256")); + chainObject.put("length", VerifyStakedToken.tokenChain.length()); + + tokenChainsList.put(chainObject); + } else { + ForkResolutionLogger.debug("Node " + pinListPledgeToken.get(i).toString() + " have not responded with token chain"); + } + } + ForkResolutionLogger.debug("Token chain details from pinned nodes received"); + + /** + * Remove token chains that do not contain transfer token + */ + for (int i = 0; i < tokenChainsList.length(); i++) { + String chainString = tokenChainsList.getJSONObject(i).getJSONArray("chain").toString(); + if(!chainString.contains(transferToken)) + tokenChainsList.remove(i); + } + + ForkResolutionLogger.debug("Token chains to be iterated:"); + for (int i = 0; i < tokenChainsList.length(); i++) { + ForkResolutionLogger.debug(tokenChainsList.getJSONObject(i).getString("node")); + } + + /** + * Create hashes and verify remaining token chains + */ + + /** + * Iterate through chains until transfer token found in the object with correct receiver + */ + boolean includedCheck = true; + for (int i = 0; i < tokenChainsList.length(); i++) { + JSONArray chain = tokenChainsList.getJSONObject(i).getJSONArray("chain"); + includedCheck = true; + for (int j = chain.length() - 1; j > 0; j--) { + ForkResolutionLogger.debug("Object " + j); + JSONObject chainIndexObject = chain.getJSONObject(j); + if (chainIndexObject.has("tokensPledgedWith")) { + String tokensPledgedWithString = chainIndexObject.get("tokensPledgedWith").toString(); + ForkResolutionLogger.debug("tokensPledgedWithString: " + tokensPledgedWithString + " pledgedToken: " + pledgedToken); + if (tokensPledgedWithString.contains(transferToken)) { + ForkResolutionLogger.debug("tokensPledgedWithString.contains(pledgedToken)"); + String receiverPID = getValues(DATA_PATH.concat("DataTable.json"), "peerid", "didHash", chainIndexObject.getString("receiver")); + ForkResolutionLogger.debug("Receiver: " + receiverPID + " Node: " + tokenChainsList.getJSONObject(i).getString("node")); + if(receiverPID.equals(tokenChainsList.getJSONObject(i).getString("node"))) { + ForkResolutionLogger.debug("Receiver IDs match"); + if (j < chain.length() - 1) { + resolutionMessage = "<1> Token Pledged correctly in the appropriate level"; + ForkResolutionLogger.debug(" <1> Token Pledged correctly in the appropriate level"); + includedCheck = true; + break; + } else { + resolutionMessage = "<2> Token Pledged maliciously. Present in the current level"; + ForkResolutionLogger.debug(" <2> Token Pledged maliciously. Present in the current level"); + includedCheck = false; + } + } else{ + resolutionMessage = "<3> Wrong pledge object"; + ForkResolutionLogger.debug("<3> Wrong pledge object"); + includedCheck = false; + } + } else { + resolutionMessage = " <4> Token Chain object does not contain the pledged token details"; + ForkResolutionLogger.debug(" <4> Token Chain object does not contain the pledged token details"); + includedCheck = false; + } + } else { + resolutionMessage = "<5> Token Chain Object does not have pledge details"; + ForkResolutionLogger.debug(" <5> Token Chain Object does not have pledge details"); + includedCheck = false; + } + } + ForkResolutionLogger.debug("Token " + transferToken + " was pledged for " + pledgedToken + " and check status for token chain of " + tokenChainsList.getJSONObject(i).getString("node") + " is " + includedCheck); + } + if (includedCheck) + return true; + ForkResolutionLogger.debug("Transfer token " + transferToken + " not found in any pledged token chains"); + return false; + } else { + ForkResolutionLogger.debug("Pledged token has no pins. Passed !!!"); + return true; + } + }else { + ForkResolutionLogger.debug("Transfer token " + transferToken + " has no multiple pins. Passed !!!"); + return true; + } + } +} \ No newline at end of file diff --git a/src/com/rubix/Consensus/InitiatorConsensus.java b/src/com/rubix/Consensus/InitiatorConsensus.java index 70997351..bc71c104 100644 --- a/src/com/rubix/Consensus/InitiatorConsensus.java +++ b/src/com/rubix/Consensus/InitiatorConsensus.java @@ -287,8 +287,8 @@ public static JSONArray start(String data, IPFS ipfs, int PORT, int index, Strin } while (quorumResponse[index] < minQuorum(quorumSize)) { } - InitiatorConsensusLogger.debug("between Q1- to Q" + quorumSize - + " for index " + index); +// InitiatorConsensusLogger.debug("between Q1- to Q" + quorumSize +// + " for index " + index); quorumSign(didHash, hash, qResponse[j], "", index, quorumSize, alphaSize); quorumWithShares.add(quorumPeersObject.getString(j)); @@ -306,8 +306,8 @@ public static JSONArray start(String data, IPFS ipfs, int PORT, int index, Strin IPFSNetwork.executeIPFSCommands( "ipfs p2p close -t /p2p/" + quorumID[j]); } - InitiatorConsensusLogger.debug("Quorum Count : " + quorumResponse - + "Signature count : " + quorumSignature.length()); + InitiatorConsensusLogger.debug("Quorum Count : " + quorumResponse.length + + " Signature count : " + quorumSignature.length()); } else { InitiatorConsensusLogger .debug("node failed authentication with index " + index @@ -508,8 +508,7 @@ public static JSONArray start(String data, IPFS ipfs, int PORT, int index, Strin } while (quorumResponse[index] < minQuorum(quorumSize)) { } - InitiatorConsensusLogger - .debug("between Q1- to Q" + quorumSize + " for index " + index); +// InitiatorConsensusLogger.debug("between Q1- to Q" + quorumSize + " for index " + index); quorumSign(didHash, hash, quorumsPrivateShareSign, quorumsPrivateKeySign, index, quorumSize, alphaSize); quorumWithShares.add(quorumPeersObject.getString(j)); while (quorumSignature diff --git a/src/com/rubix/Consensus/InitiatorProcedure.java b/src/com/rubix/Consensus/InitiatorProcedure.java index f8c61fa5..3ba0af04 100644 --- a/src/com/rubix/Consensus/InitiatorProcedure.java +++ b/src/com/rubix/Consensus/InitiatorProcedure.java @@ -10,6 +10,7 @@ import java.security.PublicKey; import com.rubix.Constants.ConsensusConstants; +import com.rubix.ConvinientTransfers.Sender; import com.rubix.SplitandStore.SeperateShares; import com.rubix.SplitandStore.Split; import com.rubix.TokenTransfer.TokenSender; @@ -56,7 +57,7 @@ public static void consensusSetUp( JSONArray gammaList = dataObject.optJSONArray("gammaList"); */ String senderPayloadSign = dataObject.optString("senderPayloadSign"); senderSignQ = dataObject.optString("sign"); - String Hash = TokenSender.authSenderByRecHash; + String Hash = Sender.authSenderByRecHash; if (operation.equals("new-credits-mining")) { @@ -78,7 +79,7 @@ public static void consensusSetUp( } else if (operation.equals("")) { - authQuorumHash = calculateHash(TokenSender.authSenderByRecHash.concat(receiverDidIpfs), "SHA3-256"); + authQuorumHash = calculateHash(Sender.authSenderByRecHash.concat(receiverDidIpfs), "SHA3-256"); } diff --git a/src/com/rubix/ConvinientTransfer/Sender.java b/src/com/rubix/ConvinientTransfer/Sender.java new file mode 100644 index 00000000..7d88f46a --- /dev/null +++ b/src/com/rubix/ConvinientTransfer/Sender.java @@ -0,0 +1,1796 @@ +package com.rubix.ConvinientTransfer; + +import com.rubix.Consensus.InitiatorConsensus; +import com.rubix.Consensus.InitiatorProcedure; +import com.rubix.Resources.Functions; +import com.rubix.Resources.IPFSNetwork; +import com.rubix.TokenTransfer.TransferPledge.Initiator; +import com.rubix.TokenTransfer.TransferPledge.Unpledge; + +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 java.net.Socket; +import java.net.SocketException; +import java.net.URL; +import java.net.UnknownHostException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static com.rubix.NFTResources.NFTFunctions.*; +import static com.rubix.Resources.Functions.*; +import static com.rubix.Resources.IPFSNetwork.*; + +public class Sender { + private static final Logger SenderLogger = Logger.getLogger(Sender.class); + private static final Logger eventLogger = Logger.getLogger("eventLogger"); + public static BufferedReader serverInput; + private static JSONObject detailsObject = new JSONObject(); + private static JSONArray quorumArray = new JSONArray(); + public static String tid = null; + private static JSONArray partTokens = new JSONArray(); + private static JSONArray wholeTokens = new JSONArray(); + private static ArrayList alphaPeersList; + private static ArrayList betaPeersList; + private static ArrayList gammaPeersList; + private static int alphaSize = -1; + private static JSONArray tokenPreviousSender = new JSONArray(); + private static JSONArray wholeTokenChainHash = new JSONArray(); + private static JSONArray partTokenChainHash = new JSONArray(); + public static JSONArray lastObJsonArray = new JSONArray(); + private static JSONObject partTokenChainsPrevState = new JSONObject(); + private static String tokenChainPath = "", tokenPath = ""; + private static JSONObject amountLedger = new JSONObject(); + private static JSONArray allTokens = new JSONArray(); + private static boolean newPart = false, oldNew = false; + private static Double decimalAmount = -1.00; + private static String PART_TOKEN_CHAIN_PATH = TOKENCHAIN_PATH.concat("PARTS/"); + private static String PART_TOKEN_PATH = TOKENS_PATH.concat("PARTS/"); + private static String senderPayloadHash = null; + private static int intPart = -1; + private static int wholeAmount = -1; + private static PrintStream output; + private static BufferedReader input; + private static Socket senderSocket; + private static boolean senderMutex = false; + public static String authSenderByRecHash; + public static JSONObject partTokenChainArrays = new JSONObject(); + + + public static void resetVariables() { + detailsObject = new JSONObject(); + quorumArray = new JSONArray(); + tid = null; + partTokens = new JSONArray(); + wholeTokens = new JSONArray(); + alphaPeersList = new ArrayList<>(); + betaPeersList = new ArrayList<>(); + gammaPeersList = new ArrayList<>(); + alphaSize = -1; + tokenPreviousSender = new JSONArray(); + wholeTokenChainHash = new JSONArray(); + partTokenChainHash = new JSONArray(); + lastObJsonArray = new JSONArray(); + partTokenChainsPrevState = new JSONObject(); + tokenChainPath = ""; + tokenPath = ""; + amountLedger = new JSONObject(); + allTokens = new JSONArray(); + newPart = false; + oldNew = false; + decimalAmount = -1.00; + PART_TOKEN_CHAIN_PATH = TOKENCHAIN_PATH.concat("PARTS/"); + PART_TOKEN_PATH = TOKENS_PATH.concat("PARTS/"); + senderPayloadHash = null; + intPart = -1; + wholeAmount = -1; + senderMutex = false; + authSenderByRecHash = ""; + SenderLogger.debug("Cleanup completed"); + partTokenChainArrays = new JSONObject(); + } + + /** + * A sender node to transfer tokens + * + * @param data Details required for tokenTransfer + * @param ipfs IPFS instance + * @param port Sender port for communication + * @return Transaction Details (JSONObject) + * @throws IOException handles IO Exceptions + * @throws JSONException handles JSON Exceptions + * @throws NoSuchAlgorithmException handles No Such Algorithm Exceptions + */ + public static JSONObject SendPartA(String data, IPFS ipfs, int port) throws JSONException, IOException, Exception,UnknownHostException { + repo(ipfs); + resetVariables(); + JSONObject APIResponse = new JSONObject(); + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + SenderLogger.debug("Transfer Part A"); + + JSONObject challengeObject = new JSONObject(); + + detailsObject = new JSONObject(data); + String receiverDidIpfsHash = detailsObject.getString("receiverDidIpfsHash"); + String receiverPeerId = getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", receiverDidIpfsHash); + syncDataTableByDID(receiverDidIpfsHash); + String pvt = detailsObject.getString("pvt"); + double requestedAmount = detailsObject.getDouble("amount"); + int type = detailsObject.getInt("type"); + String comment = detailsObject.getString("comment"); + String keyPass = detailsObject.getString("pvtKeyPass"); + PrivateKey pvtKey = null; + pvtKey = getPvtKey(keyPass, 1); + + // If user enters wrong pvt key password + if (pvtKey == null) { + APIResponse.put("message", + "Incorrect password entered for Private Key, cannot proceed with the transaction"); + SenderLogger.warn("Incorrect Private Key password entered"); + return APIResponse; + } + + // detailsObject.remove("pvtKeyPass"); + + APIResponse = new JSONObject(); + + intPart = (int) requestedAmount; + String senderPeerID = getPeerID(DATA_PATH + "DID.json"); + String senderDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", senderPeerID); + + if (senderMutex) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender busy. Try again later"); + SenderLogger.warn("Sender busy"); + return APIResponse; + } + + senderMutex = true; + + 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); + } + + SenderLogger.debug("Requested Part: " + requestedAmount); // 2 + SenderLogger.debug("Int Part: " + intPart); // 2 + String bankFile = readFile(PAYMENTS_PATH.concat("BNK00.json")); + JSONArray bankArray = new JSONArray(bankFile); // 18 + + // wholeAmount =2 ; + if (intPart <= bankArray.length()) + wholeAmount = intPart; + else + wholeAmount = bankArray.length(); + + + for (int i = 0; i < wholeAmount; i++) { + wholeTokens.put(bankArray.getJSONObject(i).getString("tokenHash")); // 2 + } + + // TokenSenderLogger.debug("wholeTokens is "+wholeTokens.toString()); + + // TokenSenderLogger.debug("wholeTokens length is "+wholeTokens.length()); + for (int i = 0; i < wholeTokens.length(); i++) { // 2 + String tokenRemove = wholeTokens.getString(i); + for (int j = 0; j < bankArray.length(); j++) { + if (bankArray.getJSONObject(j).getString("tokenHash").equals(tokenRemove)) + bankArray.remove(j); + } + } + + 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"); + if (!(token.exists() && tokenchain.exists())) { + SenderLogger.info("Tokens Not Verified"); + senderMutex = false; + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Invalid token(s)"); + return APIResponse; + + } + String wholeTokenHash = add(TOKENS_PATH + wholeTokens.get(i), ipfs); + pin(wholeTokenHash, ipfs); + 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(); + + if (tokenChainFileArray.length() > 0) { + // JSONObject lastObject = + // tokenChainFileArray.getJSONObject(tokenChainFileArray.length() - 1); + + for (int j = 0; j < tokenChainFileArray.length(); j++) { + +// TokenSenderLogger.debug("Reading token chain block = "+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); + + } + + decimalAmount = requestedAmount - wholeAmount; + decimalAmount = formatAmount(decimalAmount); + + SenderLogger.debug("Decimal Part: " + decimalAmount); + if (decimalAmount > 0.000D) { + SenderLogger.debug("Decimal Amount > 0.000D"); + String partFileContent = readFile(partTokensFile.toString()); + JSONArray partContentArray = new JSONArray(partFileContent); + + if (partContentArray.length() == 0) { + newPart = true; + String chosenToken = bankArray.getJSONObject(0).getString("tokenHash"); + partTokens.put(chosenToken); + amountLedger.put(chosenToken, formatAmount(decimalAmount)); + + } else { + Double counter = decimalAmount; + JSONArray selectParts = new JSONArray(partFileContent); + while (counter > 0.000D) { + counter = formatAmount(counter); + if (!(selectParts.length() == 0)) { + SenderLogger.debug("Old Parts"); + String currentPartToken = selectParts.getJSONObject(0).getString("tokenHash"); + Double currentPartBalance = partTokenBalance(currentPartToken); + currentPartBalance = formatAmount(currentPartBalance); + if (counter >= currentPartBalance) + amountLedger.put(currentPartToken, formatAmount(currentPartBalance)); + else + amountLedger.put(currentPartToken, formatAmount(counter)); + + partTokens.put(currentPartToken); + counter -= currentPartBalance; + selectParts.remove(0); + } else { + oldNew = true; + String chosenToken = bankArray.getJSONObject(0).getString("tokenHash"); + partTokens.put(chosenToken); + amountLedger.put(chosenToken, formatAmount(counter)); + File tokenFile = new File(TOKENS_PATH.concat(chosenToken)); + tokenFile.renameTo(new File(PART_TOKEN_PATH.concat(chosenToken))); + 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); + } else { + String shiftedContent = readFile(PAYMENTS_PATH.concat("ShiftedTokens.json")); + JSONArray shiftedArray = new JSONArray(shiftedContent); + shiftedArray.put(chosenToken); + writeToFile(PAYMENTS_PATH.concat("ShiftedTokens.json"), shiftedArray.toString(), false); + } + counter = 0.000D; + } + } + } + } + + if (newPart) { + tokenChainPath = TOKENCHAIN_PATH; + tokenPath = TOKENS_PATH; + } else { + tokenChainPath = TOKENCHAIN_PATH.concat("PARTS/"); + tokenPath = TOKENS_PATH.concat("PARTS/"); + } + + for (int i = 0; i < partTokens.length(); i++) { + File token = new File(tokenPath.concat(partTokens.getString(i))); + File tokenchain = new File(tokenChainPath.concat(partTokens.getString(i)) + ".json"); + if (!(token.exists() && tokenchain.exists())) { + if (!token.exists()) + SenderLogger.debug("Token File for parts not available"); + if (!tokenchain.exists()) + SenderLogger.debug("Token Chain File for parts not available"); + + SenderLogger.info("Tokens Files Missing"); + senderMutex = false; + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Invalid part token(s)"); + return APIResponse; + + } + 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); + for (int j = 0; j < finalChainArray.length(); j++) { + JSONObject object = finalChainArray.getJSONObject(j); + /* + * if (finalChainArray.length() == 1) { object.put("previousHash", ""); + * object.put("nextHash", ""); } else if (finalChainArray.length() > 1) { if (j + * == 0) { object.put("previousHash", ""); 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("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")); } } + */ + + if (object.has("nextHash") && object.has("previousHash")) { + object.remove("nextHash"); + object.remove("previousHash"); + } + + chainArray.put(object); + + } + + partTokenChainsPrevState.put(partTokens.getString(i), chainArray); + // TokenSenderLogger.debug("Part token chain to be sent for verification: + // "+prevStateChainContent); + + writeToFile(tokenChainPath.concat(partTokens.getString(i)).concat(".json"), chainArray.toString(), false); + + partTokenChainHash.put(add(tokenChainPath.concat(partTokens.getString(i)).concat(".json"), ipfs)); + } + SenderLogger.debug("Completed tokens selection"); + + authSenderByRecHash = calculateHash( + wholeTokens.toString() + wholeTokenChainHash.toString() + partTokens.toString() + + partTokenChainHash.toString() + receiverDidIpfsHash + senderDidIpfsHash + comment, + "SHA3-256"); + // TokenSenderLogger.debug("Hash to verify Sender: " + authSenderByRecHash); + tid = calculateHash(authSenderByRecHash, "SHA3-256"); + + challengeObject.put("authSenderByRecHash", authSenderByRecHash); + + 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)); + + 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); + senderMutex = false; + return APIResponse; + } + + syncDataTable(receiverDidIpfsHash, null); + + if (!receiverPeerId.equals("")) { + swarmConnectP2P(receiverPeerId, ipfs); + SenderLogger.debug("Swarm connected with " + receiverPeerId); + } else { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver Peer ID null"); + SenderLogger.warn("Receiver Peer ID null"); + senderMutex = false; + return APIResponse; + } + + String receiverWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "didHash", + receiverDidIpfsHash); + if (!receiverWidIpfsHash.equals("")) { + nodeData(receiverDidIpfsHash, receiverWidIpfsHash, ipfs); + } else { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver WID null"); + SenderLogger.warn("Receiver WID null"); + senderMutex = false; + return APIResponse; + } + + JSONArray alphaQuorum = new JSONArray(); + + switch (type) { + case 1: { + + quorumArray = getQuorum(senderDidIpfsHash, receiverDidIpfsHash, allTokens.length()); + break; + } + + case 2: { + File quorumFile = new File(DATA_PATH.concat("quorumlist.json")); + if (!quorumFile.exists()) { + SenderLogger.error("Quorum List for Subnet not found"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Quorum List for Subnet not found"); + return APIResponse; + } else { + String quorumList = readFile(DATA_PATH + "quorumlist.json"); + if (quorumList != null) { + quorumArray = new JSONArray(readFile(DATA_PATH + "quorumlist.json")); + } else { + SenderLogger.error("File for Quorum List for Subnet is empty"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "File for Quorum List for Subnet is empty"); + return APIResponse; + } + + } + + break; + } + case 3: { + quorumArray = detailsObject.getJSONArray("quorum"); + break; + } + default: { + SenderLogger.error("Unknown quorum type input, cancelling transaction"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Unknown quorum type input, cancelling transaction"); + return APIResponse; + + } + } + + if (quorumArray.length() > 7) { + quorumArray = cleanQuorum(quorumArray, senderDidIpfsHash, receiverDidIpfsHash, 7); + } + + String errMessage = null; + for (int i = 0; i < quorumArray.length(); i++) { + + if (quorumArray.get(i).equals(senderDidIpfsHash)) { + SenderLogger.error("SenderDID " + senderDidIpfsHash + " cannot be a Quorum"); + errMessage = "SenderDID " + senderDidIpfsHash; + } + if (quorumArray.get(i).equals(receiverDidIpfsHash)) { + SenderLogger.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; + } + + } + + +// //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 + 10); + + if (!quorumSanityCheck) { + sanityFailedQuorum.put(quorumPeerID); + if (i <= 6) + alphaCheck++; + } + } + + if (alphaCheck > 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)); + SenderLogger.warn("Quorum: ".concat(message.concat(sanityMessage))); + return APIResponse; + } +// //sanity check for Quorum - Ends + long startTime, endTime, totalTime; + + QuorumSwarmConnect(quorumArray, ipfs); + + alphaSize = quorumArray.length(); + + for (int i = 0; i < alphaSize; i++) + alphaQuorum.put(quorumArray.getString(i)); + + startTime = System.currentTimeMillis(); + + alphaPeersList = QuorumCheck(alphaQuorum, alphaSize); + + endTime = System.currentTimeMillis(); + totalTime = endTime - startTime; + eventLogger.debug("Quorum Check " + totalTime); + + if (alphaPeersList.size() < minQuorum(alphaSize)) { + updateQuorum(quorumArray, null, false, type); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Quorum Members not available"); + SenderLogger.warn("Quorum Members not available"); + senderMutex = false; + return APIResponse; + } + + SenderLogger.debug("Final Selected Alpha Members: " + alphaPeersList); + JSONArray alphaList = new JSONArray(); + for (int i = 0; i < alphaPeersList.size(); i++) { + alphaList.put(alphaPeersList.get(i)); + } + + int numberOfTokensToPledge = 0; + if (wholeAmount > 0) { + numberOfTokensToPledge += wholeAmount; + if (decimalAmount > 0) + numberOfTokensToPledge += 1; + } else + numberOfTokensToPledge = 1; + + SenderLogger.debug("Amount being transferred: " + requestedAmount + + " and number of tokens required to be pledged: " + numberOfTokensToPledge); + + JSONObject dataToSendToInitiator = new JSONObject(); + dataToSendToInitiator.put("alphaList", alphaList); + dataToSendToInitiator.put("tokenList", wholeTokens); + dataToSendToInitiator.put("amount", numberOfTokensToPledge); + dataToSendToInitiator.put("tid", tid); + dataToSendToInitiator.put("pvt", pvt); + dataToSendToInitiator.put("pvtKeyPass", keyPass); + dataToSendToInitiator.put("sender", senderDidIpfsHash); + dataToSendToInitiator.put("receiver", receiverDidIpfsHash); + + // TokenSenderLogger.debug("Details being sent to Initiator: " + + // dataToSendToInitiator); + + boolean abort = Initiator.pledgeSetUp(dataToSendToInitiator.toString(), ipfs, 22143); + if (abort) { + Initiator.abort = false; + updateQuorum(quorumArray, null, false, type); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + if (Initiator.abortReason.has("Quorum")) + APIResponse.put("message", "Alpha Node " + Initiator.abortReason.getString("Quorum") + " " + + Initiator.abortReason.getString("Reason")); + else + APIResponse.put("message", Initiator.abortReason.getString("Reason")); + SenderLogger.warn("Quorum Members with insufficient Tokens/Credits"); + senderMutex = false; + Initiator.abortReason = new JSONObject(); + return APIResponse; + } else { + JSONArray array = Initiator.quorumWithHashesArray; + challengeObject.put("pledgeDetails", array); + + } + + SenderLogger.debug("Nodes that pledged tokens: " + Initiator.pledgedNodes); + + /** + * Send the array without sender sign calculated + */ + JSONArray newChains = new JSONArray(); + for (int i = 0; i < intPart; i++) { + JSONObject lastObject = new JSONObject(); + // lastObject.put("senderSign", ""); + lastObject.put("sender", senderDidIpfsHash); + lastObject.put("group", allTokens); + lastObject.put("comment", comment); + lastObject.put("tid", tid); + lastObject.put("receiver", receiverDidIpfsHash); + lastObject.put("pledgeToken", ""); + lastObject.put("tokensPledgedFor", allTokens); + lastObject.put("tokensPledgedWith", Initiator.pledgedTokensArray); + lastObject.put("distributedObject", Initiator.distributedObject); + + String tokenChainFileContent = readFile(TOKENCHAIN_PATH + wholeTokens.get(i) + ".json"); + JSONArray tokenChain = new JSONArray(tokenChainFileContent); + tokenChain.put(lastObject); + lastObJsonArray.put(lastObject); + + String tokenChainHash = calculateHash(tokenChain.toString(), "SHA3-256"); + JSONObject tokenObject = new JSONObject(); + tokenObject.put("token", wholeTokens.getString(i)); + tokenObject.put("hash", tokenChainHash); + newChains.put(tokenObject); + } + challengeObject.put("lastObject", newChains); + senderPayloadHash = calculateHash(allTokens.toString() + senderDidIpfsHash + comment, "SHA3-256"); + + challengeObject.put("senderPayloadSign", senderPayloadHash); + + FileWriter file = new FileWriter(WALLET_DATA_PATH.concat("/ChallengePayload").concat(tid).concat(".json")); + file.write(challengeObject.toString()); + file.close(); + + + JSONArray signedChains = new JSONArray(); + JSONObject payloadSigned = new JSONObject(); + File privateShareFile = new File(DATA_PATH.concat(senderDidIpfsHash).concat("/PrivateShare.png")); + + if (privateShareFile.exists()) { + payloadSigned.put("authSenderByRecHash", getSignFromShares(pvt, authSenderByRecHash)); + payloadSigned.put("senderPayloadSign", getSignFromShares(pvt, senderPayloadHash)); + for (int i = 0; i < intPart; i++) { + JSONObject tokenObject = newChains.getJSONObject(i); + // JSONArray chainArray = tokenObject.getJSONArray("chain"); + // JSONObject lastObject = chainArray.getJSONObject(chainArray.length() - 1); + // String senderSign = getSignFromShares(pvt, authSenderByRecHash); + // lastObject.put("senderSign", senderSign); + + // chainArray.remove(chainArray.length() - 1); + // chainArray.put(lastObject); + + // String chainHash = calculateHash(chainArray.toString(), "SHA3-256"); + String chainSign = getSignFromShares(pvt, newChains.getJSONObject(i).getString("hash")); + tokenObject.put("chainSign", chainSign); + signedChains.put(tokenObject); + } + payloadSigned.put("lastObject", signedChains); + + FileWriter payloadfile = new FileWriter( + WALLET_DATA_PATH.concat("/SignPayload").concat(tid).concat(".json")); + payloadfile.write(payloadSigned.toString()); + payloadfile.close(); + + JSONArray quorumWithSignsArray = new JSONArray(); + JSONArray pledgeArray = Initiator.quorumWithHashesArray; + if (pledgeArray.length() == 0) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Not enough token to pledge"); + SenderLogger.warn("Pledging failed"); + return APIResponse; + } + + // TokenSenderLogger.debug("pledge object is " + pledgeArray.toString()); + + for (int i = 0; i < Initiator.quorumWithHashesArray.length(); i++) { + JSONObject jsonObject = Initiator.quorumWithHashesArray.getJSONObject(i); + Iterator keys = jsonObject.keys(); + // TokenSenderLogger.debug("jsonObject is " + jsonObject.toString()); + JSONObject pledgeSignedObject = new JSONObject(); + String key = ""; + JSONArray hashAndSignsArray = new JSONArray(); + while (keys.hasNext()) { + key = keys.next(); + if (jsonObject.get(key) instanceof JSONArray) { + // do something with jsonObject here + + JSONArray hashArray = new JSONArray(jsonObject.get(key).toString()); + for (int j = 0; j < hashArray.length(); j++) { + String sign = getSignFromShares(pvt, hashArray.get(j).toString()); + pledgeSignedObject.put("hash", hashArray.get(j)); + pledgeSignedObject.put("sign", sign); + hashAndSignsArray.put(pledgeSignedObject); + } + } + } + JSONObject signObject = new JSONObject(); + signObject.put(key, hashAndSignsArray); + // TokenSenderLogger.debug("signObject is " + signObject); + quorumWithSignsArray.put(signObject); + + } + + payloadSigned.put("pledgeDetails", quorumWithSignsArray); + // TokenSenderLogger.debug("pledgeDetails: " + quorumWithSignsArray); + + FileWriter spfile = new FileWriter(WALLET_DATA_PATH.concat("/signedPayload").concat(tid).concat(".json")); + spfile.write(payloadSigned.toString()); + spfile.close(); + + senderMutex = false; + return SendPartB(payloadSigned, ipfs, port); + } + senderMutex = false; + return challengeObject; + } + + public static JSONObject SendPartB(JSONObject signPayload, IPFS ipfs, int port) + throws JSONException, IOException, InterruptedException, ParseException,Exception { + + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + SenderLogger.debug("Transfer Part B"); + + + String senderSign = signPayload.getString("authSenderByRecHash"); + JSONObject APIResponse = new JSONObject(); + String receiverDidIpfsHash = detailsObject.getString("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"); + String keyPass = detailsObject.getString("pvtKeyPass"); + + PrivateKey pvtKey = getPvtKey(keyPass, 1); + String senderPeerID = getPeerID(DATA_PATH + "DID.json"); + String senderDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", senderPeerID); + JSONArray quorumWithSignsArray = signPayload.getJSONArray("pledgeDetails"); + JSONArray signedChains = signPayload.getJSONArray("lastObject"); + + // If user enters wrong pvt key password + if (pvtKey == null) { + APIResponse.put("message", + "Incorrect password entered for Private Key, cannot proceed with the transaction"); + SenderLogger.warn("Incorrect Private Key password entered"); + return APIResponse; + } + + SenderLogger.debug("Sender IPFS forwarding to DID: " + receiverDidIpfsHash + " PeerID: " + receiverPeerId); + forward(receiverPeerId, port, receiverPeerId); + SenderLogger.debug("Forwarded to " + receiverPeerId + " on " + port); + senderSocket = new Socket("127.0.0.1", port); + + input = new BufferedReader(new InputStreamReader(senderSocket.getInputStream())); + output = new PrintStream(senderSocket.getOutputStream()); + + long startTime = System.currentTimeMillis(); + + /** + * Sending Sender Peer ID to Receiver Receiver to authenticate Sender's DID + * (Identity) + */ + output.println("PartB"); + output.println(senderPeerID); + SenderLogger.debug("Sent PeerID"); + + String peerAuth; + try { + peerAuth = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Sender Auth"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "is unable to respond! - Sender Auth"); + + return APIResponse; + } + + if (peerAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.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; + + } else if (peerAuth != null && (!peerAuth.equals("200"))) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.info("Sender Data Not Available"); + 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 Data Not Available"); + return APIResponse; + + } + + String pvtKeyType = privateKeyAlgorithm(1); + // String senderSignWithPvtKey = pvtKeySign(senderSign, pvtKey, pvtKeyType); + + + + for (int i = 0; i < partTokens.length(); i++) { + String chainContent = readFile(tokenChainPath.concat(partTokens.getString(i)).concat(".json")); + JSONArray chainArray = new JSONArray(chainContent); + JSONObject newLastObject = new JSONObject(); + /* + * if (chainArray.length() == 0) { newLastObject.put("previousHash", ""); + * + * } 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")); } + */ + + Double amount = formatAmount(amountLedger.getDouble(partTokens.getString(i))); + + newLastObject.put("senderSign", senderSign); + newLastObject.put("sender", senderDidIpfsHash); + newLastObject.put("receiver", receiverDidIpfsHash); + newLastObject.put("comment", comment); + newLastObject.put("tid", tid); + newLastObject.put("role", "Sender"); + newLastObject.put("amount", amount); + chainArray.put(newLastObject); + partTokenChainArrays.put(partTokens.getString(i), chainArray); + + } + JSONArray proofOfWork = new JSONArray(); + for (int i = 0; i < wholeTokens.length(); i++) { + File proofFile = new File(TOKENCHAIN_PATH + "Proof/" + wholeTokens.getString(i) + ".proof"); + if (proofFile.exists()) { + String proofCID = add(TOKENCHAIN_PATH + "Proof/" + wholeTokens.getString(i) + ".proof", ipfs); + JSONObject proofObject = new JSONObject(); + proofObject.put("token", wholeTokens.getString(i)); + proofObject.put("cid", proofCID); + proofOfWork.put(proofObject); + } + } + JSONObject tokenDetails = new JSONObject(); + tokenDetails.put("whole-tokens", wholeTokens); + tokenDetails.put("whole-tokenChains", wholeTokenChainHash); + tokenDetails.put("hashSender", partTokenChainHash); + tokenDetails.put("part-tokens", partTokens); + tokenDetails.put("part-tokenChains", partTokenChainArrays); + tokenDetails.put("part-tokenChains-PrevState", partTokenChainsPrevState); + tokenDetails.put("sender", senderDidIpfsHash); + tokenDetails.put("proof", proofOfWork); + tokenDetails.put("distributedObject", Initiator.distributedObject); + String doubleSpendString = tokenDetails.toString(); + + // TokenSenderLogger.debug("tokenDetails is "+tokenDetails.toString()); + + String doubleSpend = calculateHash(doubleSpendString, "SHA3-256"); + writeToFile(LOGGER_PATH + "doubleSpend", doubleSpend, false); + SenderLogger.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("amount", requestedAmount); + tokenObject.put("amountLedger", amountLedger); + + if (Functions.multiplePinCheck(senderPeerID, tokenObject, ipfs, receiverPeerId) == 420) { + APIResponse.put("message", "Multiple Owners Found. Kindly re-initiate transaction"); + senderMutex = false; + return APIResponse; + } else { + SenderLogger.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(); + SenderLogger.debug("Token Auth Code: " + tokenAuth); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Token Auth"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "is unable to respond! - Token Auth"); + + return APIResponse; + } + if (tokenAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.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 "419": + String pledgedTokens = input.readLine(); + JSONArray pledgedTokensArray = new JSONArray(pledgedTokens); + SenderLogger.info("These tokens are pledged " + pledgedTokensArray); + SenderLogger.info("Kindly re-initiate transaction"); + APIResponse.put("message", "Pledged Tokens " + pledgedTokensArray + ". Kindly re-initiate transaction"); + File pledgeFile = new File(PAYMENTS_PATH.concat("PledgedTokens.json")); + if (!pledgeFile.exists()) { + pledgeFile.createNewFile(); + writeToFile(PAYMENTS_PATH.concat("PledgedTokens.json"), pledgedTokensArray.toString(), false); + } else { + String pledgedContent = readFile(PAYMENTS_PATH.concat("PledgedTokens.json")); + JSONArray pledgedArray = new JSONArray(pledgedContent); + for (int i = 0; i < pledgedTokensArray.length(); i++) { + pledgedArray.put(pledgedTokensArray.getJSONObject(i)); + } + writeToFile(PAYMENTS_PATH.concat("PledgedTokens.json"), pledgedArray.toString(), false); + } + break; + case "420": + String doubleSpent = input.readLine(); + String owners = input.readLine(); + JSONArray ownersArray = new JSONArray(owners); + SenderLogger.info("Multiple Owners for " + doubleSpent); + SenderLogger.info("Owners " + ownersArray); + SenderLogger.info("Kindly re-initiate transaction"); + APIResponse.put("message", "Multiple Owners for " + doubleSpent + " Owners: " + ownersArray + + ". Kindly re-initiate transaction"); + break; + case "421": + SenderLogger.info("Consensus ID not unique. Kindly re-initiate transaction"); + APIResponse.put("message", "Consensus ID not unique. Kindly re-initiate transaction"); + break; + case "422": + SenderLogger.info("Tokens Not Verified. Kindly re-initiate transaction"); + APIResponse.put("message", "Tokens Not Verified. Kindly re-initiate transaction"); + break; + case "423": + SenderLogger.info("Broken Cheque Chain. Kindly re-initiate transaction"); + APIResponse.put("message", "Broken Cheque Chain. Kindly re-initiate transaction"); + break; + + case "425": + SenderLogger.info("Token wholly spent already. Kindly re-initiate transaction"); + APIResponse.put("message", "Token wholly spent already. Kindly re-initiate transaction"); + break; + + case "426": + SenderLogger.info("Contains Invalid Tokens. Kindly check tokens in your wallet"); + APIResponse.put("message", "Contains Invalid Tokens. Kindly check tokens in your wallet"); + break; + + case "430": + SenderLogger + .info("Token chain verification has failed. Whole token chain/chains could not be verified."); + APIResponse.put("message", "Token Chain/(s) could not be verified."); + break; + + case "431": + SenderLogger + .info("Token chain verification has failed. Part token chain/chains could not be verified."); + APIResponse.put("message", "Token Chain/(s) could not be verified."); + break; + case "432": + SenderLogger.info("Receiver unable to get Quorum(s) public data"); + APIResponse.put("message", "Receiver unable to get Quorum(s) public data"); + break; + + case "433": + SenderLogger.info("Receiver unable to get Sender public data"); + APIResponse.put("message", "Receiver unable to get Sender public data"); + break; + + } + 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"); + return APIResponse; + } + + String pinAuth; + try { + pinAuth = input.readLine(); + SenderLogger.debug("Pin Auth Code: " + pinAuth); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Pin Auth"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "is unable to respond! - Pin Auth"); + + return APIResponse; + } + if (pinAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.info("Receiver is unable to pin 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 tokens!"); + return APIResponse; + } else if (pinAuth != null && (pinAuth.contains("count mistmatch"))) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.info("Receiver is unable to pin tokens - count mismatch!"); + 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 tokens - count mismatch"); + return APIResponse; + }else { + APIResponse.put("tid", tid); + APIResponse.put("status", "Success"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("message", "Tokens transferred successfully!"); + APIResponse.put("receiver", receiverDidIpfsHash); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + output.close(); + input.close(); + senderSocket.close(); + senderMutex = false; + resetVariables(); + JSONObject partCPayload = new JSONObject(); + partCPayload.put("quorumWithSignsArray", quorumWithSignsArray); + partCPayload.put("requestedAmount", requestedAmount); + partCPayload.put("port", port); + partCPayload.put("receiverDidIpfsHash", receiverDidIpfsHash); + partCPayload.put("pvt", pvt); + partCPayload.put("type", type); + partCPayload.put("receiverPeerId", receiverPeerId); + partCPayload.put("comment", comment); + partCPayload.put("senderSign", senderSign); + partCPayload.put("signedChains", signedChains); + partCPayload.put("amount", requestedAmount); + partCPayload.put("decimalPart",decimalAmount); + SendPartC(partCPayload, ipfs); + return APIResponse; + } + + + } + + public static JSONObject SendPartC(JSONObject signPayload, IPFS ipfs) throws JSONException, IOException, InterruptedException, ParseException,Exception { + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + SenderLogger.debug("Transfer Part C"); + + JSONObject APIResponse = new JSONObject(); + String senderPeerID = getPeerID(DATA_PATH + "DID.json"); + String senderDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", senderPeerID); + + JSONArray quorumWithSignsArray = signPayload.getJSONArray("quorumWithSignsArray"); + double requestedAmount = signPayload.getDouble("requestedAmount"); + int port = signPayload.getInt("port"); + String receiverDidIpfsHash = signPayload.getString("receiverDidIpfsHash"); + String pvt = signPayload.getString("pvt"); + int type = signPayload.getInt("type"); + String receiverPeerId = signPayload.getString("receiverPeerId"); + String comment = signPayload.getString("comment"); + String senderSign = signPayload.getString("senderSign"); + JSONArray signedChains = signPayload.getJSONArray("signedChains"); + double amount = signPayload.getDouble("amount"); + double decimalAmount = signPayload.getDouble("decimalPart"); + + + JSONObject senderDetails2Receiver = new JSONObject(); + + // detailsObject.remove("pvtKeyPass"); + if (senderMutex) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender busy. Try again later"); + SenderLogger.warn("Sender busy"); + return APIResponse; + } + + senderMutex = true; + long startTime = System.currentTimeMillis(); + Initiator.pledge(quorumWithSignsArray, requestedAmount, port); + + JSONObject dataObject = new JSONObject(); + dataObject.put("tid", tid); + dataObject.put("senderPayloadHash", senderPayloadHash); + dataObject.put("senderPayloadSign", signPayload.getString("senderPayloadSign")); + 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); + dataObject.put("sign", signPayload.getString("authSenderByRecHash")); + dataObject.put("hash", authSenderByRecHash); + + InitiatorProcedure.consensusSetUp(dataObject.toString(), ipfs, SEND_PORT + 100, alphaSize, ""); + + if (InitiatorConsensus.quorumSignature.length() < (minQuorum(alphaSize))) { + SenderLogger.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; + + } + + SenderLogger.debug("Consensus Reached"); + + SenderLogger.debug("Sender IPFS forwarding to receiver: " + receiverDidIpfsHash + " PeerID: " + receiverPeerId + " - Part C"); + forward(receiverPeerId, port, receiverPeerId); + SenderLogger.debug("Forwarded to " + receiverPeerId + " on " + port); + senderSocket = new Socket("127.0.0.1", port); + + input = new BufferedReader(new InputStreamReader(senderSocket.getInputStream())); + output = new PrintStream(senderSocket.getOutputStream()); + + senderDetails2Receiver.put("tid", tid); + senderDetails2Receiver.put("pvtShareBits", pvt); + senderDetails2Receiver.put("comment", comment); + senderDetails2Receiver.put("status", "Consensus Reached"); + senderDetails2Receiver.put("quorumsign", InitiatorConsensus.quorumSignature.toString()); + senderDetails2Receiver.put("pledgeDetails", Initiator.pledgedTokensArray); + senderDetails2Receiver.put("senderDidIpfsHash", senderDidIpfsHash); + senderDetails2Receiver.put("intPart", intPart); + senderDetails2Receiver.put("wholeTokenChains", wholeTokenChainHash); + senderDetails2Receiver.put("wholeTokens", wholeTokens); + senderDetails2Receiver.put("partTokens", partTokens); + senderDetails2Receiver.put("partTokenChainsHash", partTokenChainHash); + senderDetails2Receiver.put("distributedObject", Initiator.distributedObject); + senderDetails2Receiver.put("part-tokenChains", partTokenChainArrays); + senderDetails2Receiver.put("amountLedger", amountLedger); + senderDetails2Receiver.put("amount", amount); + senderDetails2Receiver.put("decimalPart", decimalAmount); + + + + output.println("PartC"); + output.println(senderDetails2Receiver); + + String signatureAuth; + try { + signatureAuth = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Signature Auth"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "is unable to respond! - Signature Auth"); + + return APIResponse; + } + SenderLogger.info("signatureAuth : " + signatureAuth); + long endTime = System.currentTimeMillis(); + long totalTime = endTime - startTime; + if (signatureAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.info("Receiver is unable to authenticate 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 Sender!"); + return APIResponse; + } else if (signatureAuth != null && (!signatureAuth.equals("200"))) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.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; + + } + + // Sender requests for new block that is going to be added to the Token chains. + // (For Token chain auth) + output.println("Request for new blocks being added to the Token Chains"); + + String newBlocksForTokenChains; + try { + newBlocksForTokenChains = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn( + "Receiver " + receiverDidIpfsHash + " could'nt send token chain blocks for hashing and signing"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Receiver " + receiverDidIpfsHash + "couldn't send token chain blocks for hashing and signing"); + + return APIResponse; + } + + //TokenSenderLogger.debug("newBlocksForTokenChains is " + newBlocksForTokenChains); + //TokenSenderLogger.debug(""); + + //TokenSenderLogger.debug("lastObJsonArray is " + lastObJsonArray.toString()); + + JSONArray newTokenChainBlocks = new JSONArray(newBlocksForTokenChains); + JSONArray hashAndSigns = new JSONArray(); + + for (int i = 0; i < intPart; i++) { + JSONObject lastObject = lastObJsonArray.getJSONObject(i); + JSONObject receiverLastObject = newTokenChainBlocks.getJSONObject(i).getJSONObject("lastObject"); + + Map senderChainMap = lastObject.toMap(); + Map receiverChainMap = receiverLastObject.toMap(); + senderChainMap.remove("pledgeToken"); + receiverChainMap.remove("pledgeToken"); + senderChainMap.remove("distributedObject"); + receiverChainMap.remove("distributedObject"); + + + //TokenSenderLogger.debug("--------"); + //TokenSenderLogger.debug("senderChainMap " + senderChainMap.keySet().toString()); + //TokenSenderLogger.debug("senderChainMap " + senderChainMap.values().toString()); + + //TokenSenderLogger.debug("--------"); + //TokenSenderLogger.debug("receiverChainMap " + receiverChainMap.keySet().toString()); + //TokenSenderLogger.debug("receiverChainMap " + receiverChainMap.values().toString()); + + //TokenSenderLogger.debug("--------"); + + //TokenSenderLogger.debug(senderChainMap.equals(receiverChainMap) + " is the chainmap status"); + + //TokenSenderLogger.debug("signedChains is " + signedChains.toString()); + if (senderChainMap.equals(receiverChainMap)) { + + // String PvtKeySign = + // pvtKeySign(signedChains.getJSONObject(i).getString("chainSign"), pvtKey, + // privateKeyAlgorithm(1)); + + JSONObject obj = new JSONObject(); + obj.put("hash", signedChains.getJSONObject(i).getString("hash")); + obj.put("pvtShareBits", signedChains.getJSONObject(i).getString("chainSign")); + // obj.put("pvtKeySign", PvtKeySign); + + hashAndSigns.put(obj); + } else { + output.println("Token chains Not Matching"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.info("Token chains Not Matching"); + 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", "Token chains Not Matching"); + return APIResponse; + } + } + + output.println(hashAndSigns.toString()); + // Sender requests for new block that is going to be added to the part Token + // chains. +// output.println("Request for Part Token Chains to be hashed"); + +// String req_newPartTokenChains; +// try { +// req_newPartTokenChains = input.readLine(); +// TokenSenderLogger.debug("Hashing and Signing Part Token Chains."); +// } catch (SocketException e) { +// TokenSenderLogger.warn("Receiver " + receiverDidIpfsHash + " could'nt send part token chain blocks for hashing and signing"); +// 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", "null"); +// APIResponse.put("status", "Failed"); +// APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "could'nt send part token chain blocks for hashing and signing"); +// +// return APIResponse; +// } +// +// JSONObject newPartTokenChains= new JSONObject(req_newPartTokenChains); +// + +// output.println(hashesAndSigns_partTokenChains.toString()); //Sending the hashes and signs for the part token chains sent by receiver. + + SenderLogger.debug("Unpinned Tokens"); + output.println("Unpinned"); + + String confirmation; + try { + confirmation = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Pinning Auth"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "is unable to respond! - Pinning Auth"); + + return APIResponse; + } + if (confirmation == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.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"))) { + SenderLogger.warn("Multiple Owners for the token"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.info("Tokens with multiple pins"); + 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", "Tokens with multiple pins"); + return APIResponse; + + } + output.println(InitiatorProcedure.essential); + + String respAuth; + try { + respAuth = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Share Confirmation"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Receiver " + receiverDidIpfsHash + "is unable to respond! - Share Confirmation"); + + return APIResponse; + } + if (respAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.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(); + 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 process not over"); + SenderLogger.info("Incomplete Transaction"); + return APIResponse; + } + + SenderLogger.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()) + * signedQuorumList.put(keys.next()); + */ + + JSONArray QuorumSignatures = new JSONArray(InitiatorConsensus.quorumSignature.toString()); + JSONArray signedQuorumList = new JSONArray(); + JSONObject temp = new JSONObject(); + + for (int i = 0; i < QuorumSignatures.length(); i++) { + + temp = QuorumSignatures.getJSONObject(i); + signedQuorumList.put(temp.getString("quorum_did")); + } + + APIResponse.put("tid", tid); + APIResponse.put("status", "Success"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("message", "Tokens transferred successfully!"); + APIResponse.put("quorumlist", signedQuorumList); + APIResponse.put("receiver", receiverDidIpfsHash); + APIResponse.put("totaltime", totalTime); + + JSONObject transactionRecord = new JSONObject(); + transactionRecord.put("role", "Sender"); + transactionRecord.put("tokens", allTokens); + transactionRecord.put("txn", tid); + transactionRecord.put("quorumList", signedQuorumList); + transactionRecord.put("senderDID", senderDidIpfsHash); + transactionRecord.put("receiverDID", receiverDidIpfsHash); + transactionRecord.put("Date", getCurrentUtcTime()); + transactionRecord.put("totalTime", totalTime); + transactionRecord.put("comment", comment); + transactionRecord.put("essentialShare", InitiatorProcedure.essential); + 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++) { + deleteFile(TOKENS_PATH.concat(wholeTokens.getString(i))); + Functions.updateJSON("remove", PAYMENTS_PATH.concat("BNK00.json"), wholeTokens.getString(i)); + } + if (decimalAmount != 0.0) { + + if (newPart) { + SenderLogger.debug("Updating files for new parts"); + JSONObject newPartTokenObject = new JSONObject(); + newPartTokenObject.put("tokenHash", partTokens.getString(0)); + JSONArray newPartArray = new JSONArray(); + newPartArray.put(newPartTokenObject); + writeToFile(PAYMENTS_PATH.concat("PartsToken.json"), newPartArray.toString(), false); + + String bankNew = readFile(PAYMENTS_PATH.concat("BNK00.json")); + JSONArray bankNewArray = new JSONArray(bankNew); + bankNewArray.remove(0); + writeToFile(PAYMENTS_PATH.concat("BNK00.json"), bankNewArray.toString(), false); + + String newTokenChain = readFile(TOKENCHAIN_PATH + partTokens.getString(0) + ".json"); + JSONArray chainArray = new JSONArray(newTokenChain); + + JSONObject newLastObject = new JSONObject(); + /* + * if (chainArray.length() == 0) { newLastObject.put("previousHash", ""); + * + * } 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")); } + */ + + Double decimalPrtAmount = formatAmount(decimalAmount); + + newLastObject.put("senderSign", senderSign); + newLastObject.put("sender", senderDidIpfsHash); + newLastObject.put("receiver", receiverDidIpfsHash); + newLastObject.put("comment", comment); + newLastObject.put("tid", tid); + // newLastObject.put("nextHash", ""); + newLastObject.put("role", "Sender"); + newLastObject.put("amount", decimalPrtAmount); + chainArray.put(newLastObject); + + output.println("New part token chain to be hashed"); + output.println(chainArray.toString()); + + //TokenSenderLogger.debug("!@#$% 1: " + chainArray); + + String finalPartTokenChain_string; + try { + finalPartTokenChain_string = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn( + "Receiver " + receiverDidIpfsHash + " could'nt send hahsed and signed token chain blocks."); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Receiver " + receiverDidIpfsHash + " could'nt send hahsed and signed token chain blocks."); + + return APIResponse; + } + //TokenSenderLogger.debug("!@#$% 2: " + finalPartTokenChain_string); + + JSONArray newPartTokenChain = new JSONArray(finalPartTokenChain_string); + writeToFile(TOKENCHAIN_PATH + partTokens.getString(0) + ".json", newPartTokenChain.toString(), false); + + File tokenFile = new File(TOKENS_PATH.concat(partTokens.getString(0))); + tokenFile.renameTo(new File(PART_TOKEN_PATH.concat(partTokens.getString(0)))); + 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(); + JSONArray shiftedTokensArray = new JSONArray(); + shiftedTokensArray.put(partTokens.getString(0)); + writeToFile(PAYMENTS_PATH.concat("ShiftedTokens.json"), shiftedTokensArray.toString(), false); + } else { + String shiftedContent = readFile(PAYMENTS_PATH.concat("ShiftedTokens.json")); + JSONArray shiftedArray = new JSONArray(shiftedContent); + shiftedArray.put(partTokens.getString(0)); + writeToFile(PAYMENTS_PATH.concat("ShiftedTokens.json"), shiftedArray.toString(), false); + } + } else { + + JSONObject partTokenChainsToBeSentForHashing = new JSONObject(); + + SenderLogger.debug("Updating files for old parts"); + for (int i = 0; i < partTokens.length(); i++) { + String newTokenChain = readFile( + TOKENCHAIN_PATH.concat("PARTS/") + partTokens.getString(i) + ".json"); + JSONArray chainArray = new JSONArray(newTokenChain); + + JSONObject newLastObject = new JSONObject(); + + /* + * if (chainArray.length() == 0) { newLastObject.put("previousHash", ""); + * + * } 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")); } + */ + + Double amountLedgerAmount = formatAmount(amountLedger.getDouble(partTokens.getString(i))); + + newLastObject.put("senderSign", senderSign); + newLastObject.put("sender", senderDidIpfsHash); + newLastObject.put("receiver", receiverDidIpfsHash); + newLastObject.put("comment", comment); + newLastObject.put("tid", tid); + // newLastObject.put("nextHash", ""); + newLastObject.put("role", "Sender"); + newLastObject.put("amount", amountLedgerAmount); + chainArray.put(newLastObject); + + partTokenChainsToBeSentForHashing.put(partTokens.getString(i), chainArray); + + SenderLogger.debug("Checking Parts Token Balance ..."); + Double availableParts = partTokenBalance(partTokens.getString(i)); + if (availableParts >= 1.000 || availableParts <= 0.000) { + SenderLogger.debug("Wholly Spent, Removing token from parts"); + String partFileContent2 = readFile(PAYMENTS_PATH.concat("PartsToken.json")); + JSONArray partContentArray2 = new JSONArray(partFileContent2); + for (int j = 0; j < partContentArray2.length(); j++) { + if (partContentArray2.getJSONObject(j).getString("tokenHash") + .equals(partTokens.getString(i))) + partContentArray2.remove(j); + writeToFile(PAYMENTS_PATH.concat("PartsToken.json"), partContentArray2.toString(), false); + } + deleteFile(PART_TOKEN_PATH.concat(partTokens.getString(i))); + } + } + output.println("Old part token chains to be hashed"); + output.println(partTokenChainsToBeSentForHashing.toString()); + //TokenSenderLogger.debug("!@#$% 3: " + partTokenChainsToBeSentForHashing); + + String hashedPartTokenChains_string; + try { + hashedPartTokenChains_string = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn( + "Receiver " + receiverDidIpfsHash + " could'nt send hahsed and signed token chain blocks."); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Receiver " + receiverDidIpfsHash + " could'nt send hahsed and signed token chain blocks."); + + return APIResponse; + } + + //TokenSenderLogger.debug("!@#$% 4: " + hashedPartTokenChains_string); + + JSONObject finalPartTokenChains = new JSONObject(hashedPartTokenChains_string); + for (int i = 0; i < partTokens.length(); i++) { + + JSONArray chainArray = finalPartTokenChains.getJSONArray(partTokens.getString(i)); + writeToFile(TOKENCHAIN_PATH.concat("PARTS/").concat(partTokens.getString(i)).concat(".json"), + chainArray.toString(), false); + } + + 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)) + bnkArray.remove(i); + } + writeToFile(PAYMENTS_PATH.concat("BNK00.json"), bnkArray.toString(), false); + + JSONArray pArray = new JSONArray(); + JSONObject pObject = new JSONObject(); + pObject.put("tokenHash", token); + pArray.put(pObject); + writeToFile(PAYMENTS_PATH.concat("PartsToken.json"), pArray.toString(), false); + + } + } + } + SenderLogger.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<>(); + for (int i = 0; i < allTokens.length(); i++) + tokenList.add(allTokens.getString(i)); + String url = EXPLORER_IP + "/CreateOrUpdateRubixTransaction"; + URL obj = new URL(url); + HttpsURLConnection con = (HttpsURLConnection) obj.openConnection(); + + // Setting basic post request + con.setRequestMethod("POST"); + con.setRequestProperty("Accept-Language", "en-US,en;q=0.5"); + con.setRequestProperty("Accept", "application/json"); + con.setRequestProperty("Content-Type", "application/json"); + con.setRequestProperty("Authorization", "null"); + + // Serialization + JSONObject dataToSend = new JSONObject(); + dataToSend.put("transaction_id", tid); + dataToSend.put("sender_did", senderDidIpfsHash); + dataToSend.put("receiver_did", receiverDidIpfsHash); + dataToSend.put("token_id", tokenList); + dataToSend.put("token_time", (int) totalTime); + dataToSend.put("amount", requestedAmount); + String populate = dataToSend.toString(); + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("inputString", populate); + String postJsonData = jsonObject.toString(); + + // Send post request + con.setDoOutput(true); + DataOutputStream wr = new DataOutputStream(con.getOutputStream()); + wr.writeBytes(postJsonData); + wr.flush(); + wr.close(); + + int responseCode = con.getResponseCode(); + SenderLogger.debug("Sending 'POST' request to URL : " + url); + SenderLogger.debug("Post Data : " + postJsonData); + SenderLogger.debug("Response Code : " + responseCode); + + BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); + String output; + StringBuffer response = new StringBuffer(); + + while ((output = in.readLine()) != null) { + response.append(output); + } + in.close(); + + SenderLogger.debug(response.toString()); + } + + senderMutex = false; + resetVariables(); + return APIResponse; + } +} \ No newline at end of file diff --git a/src/com/rubix/ConvinientTransfers/Recipient.java b/src/com/rubix/ConvinientTransfers/Recipient.java new file mode 100644 index 00000000..c0ff69ea --- /dev/null +++ b/src/com/rubix/ConvinientTransfers/Recipient.java @@ -0,0 +1,2332 @@ +package com.rubix.ConvinientTransfers; + +import static com.rubix.Resources.Functions.*; +import static com.rubix.Resources.IPFSNetwork.*; + +import java.awt.image.BufferedImage; +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 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 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.TokenTransfer.TransferPledge.Unpledge; + +import Fork.ForkResolution; + +import static com.rubix.Resources.APIHandler.getPubKeyIpfsHash_DIDserver; +import static com.rubix.NFTResources.NFTFunctions.*; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import com.rubix.Constants.*; + +import io.ipfs.api.IPFS; + +public class Recipient { + public static Logger RecipientLogger = Logger.getLogger(Recipient.class); + + private static final JSONObject APIResponse = new JSONObject(); + private static IPFS ipfs = new IPFS("/ip4/127.0.0.1/tcp/" + IPFS_PORT); + + // 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; + JSONArray quorumSignatures = null; + + ArrayList quorumDID = new ArrayList<>(); + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + + ArrayList WholeTokenChainsWithAppendedBlock = new ArrayList(); + JSONArray hash_Signs_ForTokenChains = new JSONArray(); + JSONArray hashes_Signs_PartTokenChains = new JSONArray(); + JSONObject final_parttokenchains = new JSONObject(); + + String receiverPeerID = getPeerID(DATA_PATH + "DID.json"); + + String receiverDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", receiverPeerID); + + JSONObject temp = new JSONObject(); + temp.put("pvtShare", DATA_PATH + receiverDidIpfsHash + "/PrivateShare.png"); + String pvt = temp.getString("pvtShare"); + + RECEIVER_PORT = RECEIVER_PORT+39; + listen(receiverPeerID.concat("step"), RECEIVER_PORT); + ss = new ServerSocket(RECEIVER_PORT); + RecipientLogger.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(); + + String messageRequest = ""; + try { + messageRequest = input.readLine(); + } catch (SocketException e) { + RecipientLogger.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(); + } + RecipientLogger.debug("Message Request Received: " + messageRequest); + + if (messageRequest == null) { + RecipientLogger.warn("Sender Stream Null - Message Request"); + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender Stream Null - Message Request"); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } else if (messageRequest.contains("PartB")) { + try { + senderPeerID = input.readLine(); + } catch (SocketException e) { + RecipientLogger.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(); + } + + RecipientLogger.debug("Sender Peer ID 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"); + RecipientLogger.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"); + RecipientLogger.info("Sender details not available"); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + RecipientLogger.debug("Sender details authenticated"); + output.println("200"); + + String tokenDetails; + try { + tokenDetails = input.readLine(); + } catch (SocketException e) { + RecipientLogger.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(); + + } + RecipientLogger.debug("Token details Received: " + tokenDetails); + + 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"); + JSONObject partTokenChainsForVerification = TokenDetails.getJSONObject("part-tokenChains-PrevState"); + JSONArray partTokenChainsHash = TokenDetails.getJSONArray("hashSender"); + JSONObject distributedObject = TokenDetails.getJSONObject("distributedObject"); + + if (TokenDetails.optJSONArray("proof") != null) { + JSONArray proofArray = TokenDetails.getJSONArray("proof"); + + for (int i = 0; i < proofArray.length(); i++) { + String token = proofArray.getJSONObject(i).getString("token"); + String cid = proofArray.getJSONObject(i).getString("cid"); + String proof = get(cid, ipfs); + File proofFile = new File(TOKENCHAIN_PATH + "Proof/"); + if (!proofFile.exists()) { + proofFile.mkdirs(); + } + // TOKENCHAIN_PATH + "Proof/"+ token + ".proof" + writeToFile(proofFile.getAbsolutePath() + "/" + token + ".proof", proof, false); + RecipientLogger.debug(proofFile.getAbsolutePath()); + } + } + + JSONArray previousSendersArray = tokenObject.getJSONArray("previousSender"); +// JSONArray positionsArray = tokenObject.getJSONArray("positions"); + + Double amount = tokenObject.getDouble("amount"); + JSONObject amountLedger = tokenObject.getJSONObject("amountLedger"); + int intPart = wholeTokens.length(); + // ? multiple pin check starts + Double decimalPart = formatAmount(amount - intPart); + JSONArray doubleSpentToken = new JSONArray(); + boolean multiplePin = false; + 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 { +// RecipientLogger +// .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)); +// } +// RecipientLogger.debug("Previous Owners: " + previousSender.toString()); +// RecipientLogger.debug("Pin owners " + pinOwnersArray.toString()); +// +// ArrayList retainOrder = pinOwnersArray; +// previousSender.add(senderPeerID); +// previousSender.add(receiverPeerID); +// +// retainOrder.removeAll(previousSender); +// FunctionsLogger.debug("retain list " + retainOrder.toString()); +// +// if (retainOrder.size() > 0) { +// FunctionsLogger.debug("retain list in if " + retainOrder.toString()); +// multiplePin = true; +// +// } +// } +// } catch (IOException e) { +// +// RecipientLogger.debug("Ipfs dht find did not execute"); +// } +// } +// if (multiplePin) { +// 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"); +// RecipientLogger.debug("consensusID is " + consensusID); + writeToFile(LOGGER_PATH + "consensusID", consensusID, false); + String consensusIDIPFSHash = IPFSNetwork.addHashOnly(LOGGER_PATH + "consensusID", ipfs); + deleteFile(LOGGER_PATH + "consensusID"); + + if (!IPFSNetwork.dhtEmpty(consensusIDIPFSHash, ipfs)) { + RecipientLogger.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); + } + + if (intPart > 0) { + + boolean forkResolution = true; + // TokenReceiverLogger.debug("Whole Token Chains: " + + // wholeTokenChainContent.get(0)); + // TokenReceiverLogger.debug("Whole Token Chains: " + new + // JSONArray(wholeTokenChainContent.get(0))); + JSONArray forkedTokens = new JSONArray(); + for (int i = 0; i < wholeTokens.length(); ++i) { + + JSONArray tokenChain = new JSONArray(wholeTokenChainContent.get(i)); + JSONObject forkObject = new JSONObject(); + forkObject.put("token", wholeTokens.getString(i)); + forkObject.put("tokenChain", tokenChain); + forkObject.put("previousSendersArray", previousSendersArray); + forkObject.put("currentSender", senderPeerID); + forkObject.put("currentReceiver", receiverPeerID); + + if (tokenChain.getJSONObject(tokenChain.length() - 1).has("pledgeToken")) { +// RecipientLogger.debug("Token " + wholeTokens.getString(i) + " is a new token (SHAG structure)"); + if (!tokenChain.getJSONObject(tokenChain.length() - 1).getString("pledgeToken") + .equals("")) { +// RecipientLogger.debug("Token " + wholeTokens.getString(i) + " is a pledged token"); + forkResolution = ForkResolution.verifyUnpledgedToken(wholeTokens.getString(i), + tokenChain.getJSONObject(tokenChain.length() - 1) + .getJSONArray("tokensPledgedFor").get(0).toString(), + senderPeerID, receiverPeerID); + + } else { +// RecipientLogger.debug("Token " + wholeTokens.getString(i)+ " is a new token (SHAG structure) and not pledged"); + forkResolution = ForkResolution.check(forkObject); + } + } else { +// RecipientLogger.debug("Token " + wholeTokens.getString(i) + " is an Eismeer Token"); + forkResolution = ForkResolution.check(forkObject); + } + if (!forkResolution) { + RecipientLogger.debug("Fork found and not resolved for token: " + wholeTokens.getString(i)); + RecipientLogger.debug("Message: " + ForkResolution.resolutionMessage); + forkedTokens.put(wholeTokens.getString(i)); + } + } + if (!forkResolution) { + RecipientLogger.debug("Fork not resolved for " + forkedTokens); + output.println("418"); + output.println(forkedTokens.toString()); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Fork not resolved"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + } + + // QmWcmK38g9XcrCwhoEq3rQjNseJW2HyscoG66DWF62X6bK.proof + // BNK00.json -- unpledge + // + repo(ipfs); + String pledgeErrorMessage = ""; + if (wholeTokens.length() > 0) { + boolean pledged = true; + JSONArray pledgedTokens = new JSONArray(); + for (int i = 0; i < wholeTokens.length(); i++) { + JSONArray chain = new JSONArray(wholeTokenChainContent.get(i)); + if (chain.length() > 0) { + JSONObject pledgeBlock = chain.getJSONObject(chain.length() - 1); + // TokenReceiverLogger.debug("pledgeBlock object " + pledgeBlock.toString()); + // if (pledgeBlock.has("pledgeToken")) { + + if (pledgeBlock.optString("pledgeToken").length() > 0) { + pledged = false; + String tokenName = chain.getJSONObject(chain.length() - 1).getString("pledgeToken"); + String did = chain.getJSONObject(chain.length() - 1).getString("receiver"); + String tid = chain.getJSONObject(chain.length() - 1).getString("tid"); + String path = TOKENCHAIN_PATH + "Proof/" + tokenName + ".proof"; + File proofFile = new File(path); + if (proofFile.exists()) { + pledged = Unpledge.verifyProof(tokenName, did, tid); + } + JSONObject pledgedTokenObject = new JSONObject(); + pledgedTokenObject.put("tokenHash", wholeTokens.getString(i)); + pledgedTokens.put(pledgedTokenObject); + } + // } + } + } + if (!pledged) { + output.println("419"); + output.println(pledgedTokens.toString()); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", pledgeErrorMessage); + RecipientLogger.info(pledgeErrorMessage); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + if (!(ipfsGetFlag == intPart)) { + output.println("422"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Tokens not verified"); + RecipientLogger.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()); + tokenDetailMap = Functions.checkTokenHash(tokenDetailMap, tokenMaxValue); + + if (tokenDetailMap.isEmpty()) { + RecipientLogger.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); + RecipientLogger.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); + RecipientLogger.debug(errorMessage1); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + } + } + + } + /** Token Authenticity Check - Ends */ + + // Token Chains authenticity check starts + + RecipientLogger.debug("VERIFYING TOKEN CHAIN(S).. "); + + // For WholeTokenChains + int chainAutheticityFlag = 0; + boolean flag = false; +// RecipientLogger.debug("Verifying whole token chains.. "); + for (int i = 0; i < intPart; i++) { + + // TokenReceiverLogger.debug("Verifying whole Token Chain : " + + // wholeTokenChains.getString(i)); + + String TokenChainContent = get(wholeTokenChains.getString(i), ipfs); + + JSONArray TokenChainArray = new JSONArray(TokenChainContent); + // TokenReceiverLogger.debug("Token Chain content fetched from ipfs for + // tokenchain"+i+" : "+ TokenChainArray); + + JSONObject lastValueOnChain = TokenChainArray.getJSONObject(TokenChainArray.length() - 1); + + JSONObject forNLSScheck = new JSONObject(); + +// if(lastValueOnChain.has("hash") && lastValueOnChain.has("pvtShareBits") && lastValueOnChain.has("pvtKeySign")){ + + if (lastValueOnChain.has("hash") && lastValueOnChain.has("pvtShareBits")) { + + String hash = lastValueOnChain.getString("hash"); +// RecipientLogger.debug("Hash to check(hash) : " + hash); + String pvtShareBits = lastValueOnChain.getString("pvtShareBits"); + // String pvtKeySign = lastValueOnChain.getString("pvtKeySign"); + String prevSenderDID = lastValueOnChain.getString("sender"); + + // Editing last object before calc hash. + + JSONObject lastObj = new JSONObject(); + lastObj = TokenChainArray.getJSONObject(TokenChainArray.length() - 1); + TokenChainArray.remove(TokenChainArray.length() - 1); + lastObj.remove("hash"); + lastObj.remove("pvtShareBits"); + // lastObj.remove("pvtKeySign"); + + TokenChainArray.put(lastObj); + + // TokenReceiverLogger.debug("Token Chain Content that is to be hashed : + // "+TokenChainArray); + + String hashToCheck = calculateHash(TokenChainArray.toString(), "SHA3-256"); +// RecipientLogger.debug("@@@@@@ hashtocheck is " + hashToCheck); + +// RecipientLogger.debug("@@@@@@ Calculated Hash(hashtocheck) : " + hashToCheck); + + // TokenReceiverLogger.debug("@@@@@@ ReCalc tokenchain: " + TokenChainArray); + + // Check 1 : Hash comaprison check + if (hashToCheck.equals(hash)) { + +// RecipientLogger.debug("Hash values match."); + + // Check to ensure the sender hasnt changed the DID on the second last block to + // their DID instead of the prev sender. + // If the above is done, the sender cn easily change the contents of the chain + // and, hash and sign, and the receiver wont know. + // Hence the check. + if (prevSenderDID.equals(senderDidIpfsHash)) { + chainAutheticityFlag = 3; + break; + } + + forNLSScheck.put("did", prevSenderDID); + forNLSScheck.put("hash", hashToCheck); + forNLSScheck.put("signature", pvtShareBits); + + String prevSenderPublicKeyIpfsHash = getPubKeyIpfsHash_DIDserver(prevSenderDID, 1); // get + // public + // key + // ipfs + // hash + // of + // the + // sender. + // Need to handle the case where DID server isnt available. + + String prevSenderPubKeyStr = IPFSNetwork.get(prevSenderPublicKeyIpfsHash, ipfs); // get + // sender's + // public + // key + // from + // ipfs. + // Need to handle the case when ipfs isn't avaialble. + + String pubKeyAlgo = publicKeyAlgStr(prevSenderPubKeyStr); + + flag = Authenticate.verifySignature(forNLSScheck.toString()); + if (!flag) { + + chainAutheticityFlag = 5; + break; + } + + // Check 2: prev Sender authenticity check (Signature) + /* + * if(verifySignature(pvtShareBits,getPubKeyFromStr(prevSenderPubKeyStr, + * pubKeyAlgo),pvtKeySign,pubKeyAlgo)==true){ + * + * flag = Authenticate.verifySignature(forNLSScheck.toString()); if(!flag){ + * + * chainAutheticityFlag = 5; break; }else{ + * TokenReceiverLogger.debug("Previous sender's sign also authenticated."); + * TokenReceiverLogger.debug("Token chain "+wholeTokenChains.getString(i)+ + * "verified"); } + * + * } else { + * + * //If private key signature verification of prev sender doesn't complete. + * chainAutheticityFlag = 4; break; } + */ + + } else { + + // If hash values dont match + chainAutheticityFlag = -1; + break; + } + + } else { + // If the hash and sign are not present in the TokenChain + chainAutheticityFlag = 1; + break; + } + } + + // Returning responses after chain verification + if (chainAutheticityFlag == 1) { + + RecipientLogger.debug("Token Transfer continuing without TokenChain authentication check. (Bootstrap purpose)"); + // if condition needs to be removed after bootstrapping. + } + + // If hash values for tokenchain authenticity checks have a mismatch. + if (chainAutheticityFlag == 2) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Token Chain could not be verified"); + RecipientLogger.info("Token Chain could not be verified."); + // TokenReceiverLogger.info("Chain auth flag : "+chainAutheticityFlag); + + output.println("430"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + // If sender tries to edit the token chain with the hash and the sign. Ideally + // by putting his DID instead of prev sender's DID in the last appended block. + if (chainAutheticityFlag == 3) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Token Chain could not be verified. Malicious activity by sender"); + RecipientLogger.info("Token Chain could not be verified. Malicious activity by sender"); + // TokenReceiverLogger.info("Chain auth flag : "+chainAutheticityFlag); + + output.println("430"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + if (chainAutheticityFlag == 4) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Token Chain could not be verified. Previous sender's signature not verified"); + RecipientLogger.info("Token Chain could not be verified. Previous sender's signature not verified"); + // TokenReceiverLogger.info("Chain auth flag : "+chainAutheticityFlag); + + output.println("430"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + if (chainAutheticityFlag == 5) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Token Chain could not be verified. Previous sender's signature not verified"); + RecipientLogger.info("Token Chain could not be verified. Previous sender's signature not verified"); + // TokenReceiverLogger.info("Chain auth flag : "+chainAutheticityFlag); + + output.println("430"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + if (flag) { + RecipientLogger.debug("Whole Token Chains successfully verified !"); + } + + // For PartTokenChains + int chainAutheticityFlag2 = 0; + boolean flag2 = false; + RecipientLogger.debug("Verifying part token chains.. "); + for (int i = 0; i < partTokens.length(); i++) { + + JSONObject forNLSScheck = new JSONObject(); + JSONArray partTokenChainToVerify = new JSONArray(); + JSONObject lastValueOnChain2 = new JSONObject(); +// RecipientLogger.debug("Verifying part Token Chain : " + partTokens.getString(i)); + + partTokenChainToVerify = partTokenChainsForVerification.getJSONArray(partTokens.getString(i)); + + lastValueOnChain2 = partTokenChainToVerify.getJSONObject(partTokenChainToVerify.length() - 1); + + if ((lastValueOnChain2.has("role"))) { + + if (lastValueOnChain2.getString("role").equals("Sender")) { + + if (lastValueOnChain2.has("hash") && lastValueOnChain2.has("pvtShareBits")) { + + String hash = lastValueOnChain2.getString("hash"); +// RecipientLogger.debug("Hash to check : " + hash); + + String pvtShareBits = lastValueOnChain2.getString("pvtShareBits"); + + String requiredDID = lastValueOnChain2.getString("receiver"); + + // Editing last object before calc hash. + + JSONObject lastObj2 = new JSONObject(); + lastObj2 = partTokenChainToVerify.getJSONObject(partTokenChainToVerify.length() - 1); + partTokenChainToVerify.remove(partTokenChainToVerify.length() - 1); + lastObj2.remove("hash"); + lastObj2.remove("pvtShareBits"); + // lastObj.remove("pvtKeySign"); + + partTokenChainToVerify.put(lastObj2); + + // TokenReceiverLogger.debug("Token Chain to be hashed : " + + // partTokenChainToVerify); + + String hashToCheck = calculateHash(partTokenChainToVerify.toString(), "SHA3-256"); +// RecipientLogger.debug("Calculated Hash(hashToCheck) : " + hashToCheck); + + if (hashToCheck.equals(hash)) { +// RecipientLogger.debug("Hash values match."); + + forNLSScheck.put("did", requiredDID); + forNLSScheck.put("hash", hashToCheck); + forNLSScheck.put("signature", pvtShareBits); + + flag2 = Authenticate.verifySignature(forNLSScheck.toString()); + if (!flag2) { + + chainAutheticityFlag2 = 5; + break; + } + + } else { + + // If hash values dont match + chainAutheticityFlag2 = 2; + break; + } + } else { + // If the hash and sign are not present in the TokenChain + chainAutheticityFlag2 = 1; + break; + } + } + + else { + + if (lastValueOnChain2.has("hash") && lastValueOnChain2.has("pvtShareBits")) { + + String hash = lastValueOnChain2.getString("hash"); + // TokenReceiverLogger.debug("Hash to check : "+ hash); + + String pvtShareBits = lastValueOnChain2.getString("pvtShareBits"); + // String pvtKeySign = lastValueOnChain.getString("pvtKeySign"); + + String requiredDID = lastValueOnChain2.getString("sender"); + + // Editing last object before calc hash. + JSONObject lastObj3 = new JSONObject(); + JSONObject newobj3 = new JSONObject(); + lastObj3 = partTokenChainToVerify.getJSONObject(partTokenChainToVerify.length() - 1); + + partTokenChainToVerify.remove(partTokenChainToVerify.length() - 1); + + lastObj3.remove("hash"); + lastObj3.remove("pvtShareBits"); + + partTokenChainToVerify.put(lastObj3); + + // TokenReceiverLogger.debug("Token chain to be hashed (AFTER EDITING LAST + // BLOCK) : "+ partTokenChainToVerify); + + String hashToCheck = calculateHash(partTokenChainToVerify.toString(), "SHA3-256"); +// RecipientLogger.debug("Calculated Hash : " + hashToCheck); + + if (hashToCheck.equals(hash)) { + // TokenReceiverLogger.debug("Hash values match."); + + forNLSScheck.put("did", requiredDID); + forNLSScheck.put("hash", hashToCheck); + forNLSScheck.put("signature", pvtShareBits); + + flag2 = Authenticate.verifySignature(forNLSScheck.toString()); + if (!flag2) { + + chainAutheticityFlag2 = 5; + break; + } + + } else { + + // If hash values dont match + chainAutheticityFlag2 = 2; + break; + } + + } else { + // If the hash and sign are not present in the TokenChain + chainAutheticityFlag2 = 1; + break; + } + } + + } else if (lastValueOnChain2.has("hash") && lastValueOnChain2.has("pvtShareBits")) { + + // else if (lastValueOnChain2.has("hash") && + // lastValueOnChain2.has("pvtShareBits") && + // lastValueOnChain2.has("pvtKeySign")){ + + String hash = lastValueOnChain2.getString("hash"); + // TokenReceiverLogger.debug("Hash to check : "+ hash); + String pvtShareBits = lastValueOnChain2.getString("pvtShareBits"); + // String pvtKeySign = lastValueOnChain2.getString("pvtKeySign"); + String prevSenderDID = lastValueOnChain2.getString("sender"); + + // Editing last object before calc hash. + + JSONObject lastObj4 = new JSONObject(); + lastObj4 = partTokenChainToVerify.getJSONObject(partTokenChainToVerify.length() - 1); + partTokenChainToVerify.remove(partTokenChainToVerify.length() - 1); + lastObj4.remove("hash"); + lastObj4.remove("pvtShareBits"); + // lastObj4.remove("pvtKeySign"); + + partTokenChainToVerify.put(lastObj4); + + // TokenReceiverLogger.debug("Token Chain Content that is to be hashed : + // "+TokenChainArray); + + String hashToCheck = calculateHash(partTokenChainToVerify.toString(), "SHA3-256"); + // TokenReceiverLogger.debug("hashToCheck(partTokenChainToVerify.toString()) is + // " + hashToCheck); + + if (hashToCheck.equals(hash)) { + +// RecipientLogger.debug("Hash values match."); + + // Check to ensure the sender hasnt changed the DID on the second last block to + // their DID instead of the prev sender. + // If the above is done, the sender cn easily change the contents of the chain + // and, hash and sign, and the receiver wont know. + // Hence the check. + if (prevSenderDID.equals(senderDidIpfsHash)) { + chainAutheticityFlag = 3; + break; + } + + forNLSScheck.put("did", prevSenderDID); + forNLSScheck.put("hash", hashToCheck); + forNLSScheck.put("signature", pvtShareBits); + + String prevSenderPublicKeyIpfsHash = getPubKeyIpfsHash_DIDserver(prevSenderDID, 1); // get + // public + // key + // ipfs + // hash + // of + // the + // sender. + // Need to handle the case where DID server isnt available. + + String prevSenderPubKeyStr = IPFSNetwork.get(prevSenderPublicKeyIpfsHash, ipfs); // get + // sender's + // public + // key + // from + // ipfs. + // Need to handle the case when ipfs isn't avaialble. + + String pubKeyAlgo = publicKeyAlgStr(prevSenderPubKeyStr); + + flag = Authenticate.verifySignature(forNLSScheck.toString()); + if (!flag) { + + chainAutheticityFlag = 5; + break; + } else { + RecipientLogger.debug("Previous sender's sign also authenticated."); + // TokenReceiverLogger.debug("Token chain " + wholeTokenChains.getString(i) + + // "verified"); + } + + /* + * //Check 2: prev Sender authenticity check (Signature) + * if(verifySignature(pvtShareBits,getPubKeyFromStr(prevSenderPubKeyStr, + * pubKeyAlgo),pvtKeySign,pubKeyAlgo)==true){ + * + * flag = Authenticate.verifySignature(forNLSScheck.toString()); if(!flag){ + * + * chainAutheticityFlag = 5; break; }else{ + * TokenReceiverLogger.debug("Previous sender's sign also authenticated."); + * TokenReceiverLogger.debug("Token chain "+wholeTokenChains.getString(i)+ + * "verified"); } + * + * } else { + * + * //If private key signature verification of prev sender doesn't complete. + * chainAutheticityFlag = 4; break; } + */ + + } else { + + // If hash values dont match + chainAutheticityFlag = 2; + break; + } + + } else { + chainAutheticityFlag2 = 1; + } + + } + + // Returning responses after chain verification + + if (chainAutheticityFlag2 == 1) { + + RecipientLogger.debug( + "Token Transfer for a particular token is continuing without TokenChain authentication check. (Bootstrap purpose)"); + // if condition needs to be removed after bootstrapping. + } + + // If hash values for tokenchain authenticity checks have a mismatch. + if (chainAutheticityFlag2 == 2) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Part Token Chain could not be verified. Incorrect hash"); + RecipientLogger.info("Part Token Chain could not be verified"); + + output.println("431"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + // If sender tries to edit the token chain with the hash and the sign. Ideally + // by putting his DID instead of prev sender's DID in the last appended block. + if (chainAutheticityFlag2 == 3) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Part Token Chain could not be verified. Malicious activity by sender"); + RecipientLogger.info("Part Token Chain could not be verified. Malicious activity by sender"); + + output.println("431"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + if (chainAutheticityFlag2 == 4) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Part Token Chain could not be verified. Previous sender's signature not verified"); + RecipientLogger + .info("Part Token Chain could not be verified. Previous sender's signature not verified"); + + output.println("431"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + if (chainAutheticityFlag2 == 5) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Part Token Chain could not be verified. Previous sender's signature not verified"); + RecipientLogger + .info("Part Token Chain could not be verified. Previous sender's signature not verified"); + + output.println("431"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + if (flag2) { + RecipientLogger.debug("Part Token Chains verified !"); + } + + // Token Chain 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(); + + // TODO + 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)) ) { + if (tokenChain.length() > 0 && !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)) { + if (tokenChain.length() < minumumStakeHeight) { + // && (tokenNumber > 1204400) + if (tokenChain.length() > 0) { + 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); + // } + + /** Modifying the changes to accomodate 1/5 staking; */ + if (stakeDataArray.length() > 0 && stakeDataArray.length() <= 3) { + + /* + * if(stakeDataArray.length() > 0) { 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); + */ + + String[] stakedTokenTC = new String[stakeDataArray.length()]; + String[] stakedTokenSignTC = new String[stakeDataArray.length()]; + String[] stakerDIDTC = new String[stakeDataArray.length()]; + String[] mineIDTC = new String[stakeDataArray.length()]; + String[] mineIDSignTC = new String[stakeDataArray.length()]; + + for (int i = 0; i < stakeDataArray.length(); i++) { + + JSONObject oneOfThreeStake = stakeDataArray.getJSONObject(i); + + stakedTokenTC[i] = oneOfThreeStake.getString(MiningConstants.STAKED_TOKEN); + stakedTokenSignTC[i] = oneOfThreeStake + .getString(MiningConstants.STAKED_TOKEN_SIGN); + stakerDIDTC[i] = oneOfThreeStake.getString(MiningConstants.STAKED_QUORUM_DID); + mineIDTC[i] = oneOfThreeStake.getString(MiningConstants.MINE_ID); + mineIDSignTC[i] = oneOfThreeStake.getString(MiningConstants.MINE_ID_SIGN); + } + + RecipientLogger.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); + RecipientLogger.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); + + RecipientLogger.debug(stakerDIDTC[stakeCount]); + RecipientLogger.debug(stakedTokenTC[stakeCount]); + RecipientLogger.debug(stakedTokenSignTC[stakeCount]); + + RecipientLogger.debug(stakerDIDMineData); + RecipientLogger.debug(stakedTokenMineData); + RecipientLogger.debug(stakedTokenSignMineData); + + if (stakerDIDTC[stakeCount].equals(stakerDIDMineData) + && stakedTokenTC[stakeCount].equals(stakedTokenMineData) + && stakedTokenSignTC[stakeCount].equals(stakedTokenSignMineData)) { + + RecipientLogger.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]); + RecipientLogger.debug("detailsToVerify - " + detailsToVerify.toString()); + + if (Authenticate.verifySignature(detailsToVerify.toString())) { + + boolean minedTokenStatus = true; + ArrayList ownersArray = IPFSNetwork + .dhtOwnerCheck(stakedTokenTC[stakeCount]); + RecipientLogger.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) { + RecipientLogger.debug("Staked token is not found with staker DID: " + + stakerDIDTC[stakeCount]); +// ownerCheck = false; + invalidTokens.put(tokens); + } + + } else { + RecipientLogger.debug( + "Staking check (2) failed - unable to verify mine ID signature by staker: " + + stakerDIDTC[stakeCount]); +// ownerCheck = false; + invalidTokens.put(tokens); + } + + RecipientLogger.debug("MineID Verification Successful with Staking node: " + + stakerDIDTC[stakeCount]); + } else { + RecipientLogger.debug("Staking check (2) failed"); +// ownerCheck = false; + invalidTokens.put(tokens); + } + + RecipientLogger.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; + RecipientLogger.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"), "Get-TokenChain-Height")) { + minedTokenStatus = false; + } + } + if (!minedTokenStatus) { + RecipientLogger.debug("Staking check failed: Found staked token but token height < 46"); +// ownerCheck = false; + invalidTokens.put(tokens); + } + + RecipientLogger.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)); +// RecipientLogger.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); + RecipientLogger.debug(errorMessage); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + output.println("200"); + + 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) { + RecipientLogger.debug("Pinned All Tokens"); + output.println("Successfully Pinned"); + + } else { + output.println("count mistmatch"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "count mismacth"); + RecipientLogger.info(" Transaction failed - Pin Count"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + } else if (messageRequest.contains("PartC")) { + String senderDetails; + try { + senderDetails = input.readLine(); + } catch (SocketException e) { + RecipientLogger.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("pvtKeySign"); + String senderPvtShareBits = SenderDetails.getString("pvtShareBits"); + + String tid = SenderDetails.getString("tid"); + String comment = SenderDetails.getString("comment"); + String Status = SenderDetails.getString("status"); + String QuorumDetails = SenderDetails.getString("quorumsign"); + JSONArray pledgedDetails = SenderDetails.getJSONArray("pledgeDetails"); + + String senderDidIpfsHash = SenderDetails.getString("senderDidIpfsHash"); + int intPart = SenderDetails.getInt("intPart"); + JSONArray wholeTokenChains = SenderDetails.getJSONArray("wholeTokenChains"); + JSONArray wholeTokens = SenderDetails.getJSONArray("wholeTokens"); + JSONArray partTokens = SenderDetails.getJSONArray("partTokens"); + JSONArray partTokenChainsHash = SenderDetails.getJSONArray("partTokenChainsHash"); + JSONObject distributedObject = SenderDetails.getJSONObject("distributedObject"); + JSONObject amountLedger = SenderDetails.getJSONObject("amountLedger"); + double amount = SenderDetails.getDouble("amount"); + double decimalPart = SenderDetails.getDouble("decimalPart"); + JSONObject partTokenChains = SenderDetails.getJSONObject("part-tokenChains"); + + String BlockHash = new String(); + if (SenderDetails.toString().contains("blockHash")) { + BlockHash = SenderDetails.getString("blockHash"); + } + + 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"); + +// RecipientLogger.debug("hash is " + hash); + +// RecipientLogger.debug("Verifying Quorum ... "); +// RecipientLogger.debug("Please wait, this might take a few seconds"); + + if (!Status.equals("Consensus Failed")) { + boolean yesQuorum = false; + if (Status.equals("Consensus Reached")) { + quorumSignatures = new JSONArray(QuorumDetails); + + // String selectQuorumHash = calculateHash(senderToken, "SHA3-256"); + String verifyQuorumHash = hash; +// RecipientLogger.debug("verifyQuorumHash is " + verifyQuorumHash); + + String quorumHash = calculateHash(verifyQuorumHash.concat(receiverDidIpfsHash), "SHA3-256"); +// RecipientLogger.debug("quorumHash is " + quorumHash); +// RecipientLogger.debug("quorumHash is (verifyQuorumHash)concat(receiverDidIpfsHash)"); + + /* + * 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 QuorumMember = quorumSignatures.getJSONObject(i); + syncDataTable(QuorumMember.getString("quorum_did"), null); + String quorumWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "didHash", + QuorumMember.getString("quorum_did")); + String quorumPid = getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", + QuorumMember.getString("quorum_did")); + bootstrapConnect(quorumPid, ipfs); + + nodeData((QuorumMember.getString("quorum_did")), quorumWidIpfsHash, ipfs); + } + + for (int i = 0; i < quorumSignatures.length(); i++) { + + JSONObject quorumMember = quorumSignatures.getJSONObject(i); + + // TokenReceiverLogger.debug("Quorum sign of member " +i+ ":"+quorumMember); + + String quorumsPrivateShareSign = quorumMember.getString("quorumPrivateShareSign"); + String quorumsPrivateKeySign = quorumMember.getString("quorumPvtKeySign"); + + String QuorumPublicKeyIpfsHash = getPubKeyIpfsHash_DIDserver( + quorumMember.getString("quorum_did"), 2); // get public key ipfs hash of the quorum + // member. + + // TODO + if (QuorumPublicKeyIpfsHash.isEmpty()) { + output.println("432"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", tid); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Quorum data not available for " + quorumMember.getString("quorum_did")); + RecipientLogger.info("Quorum data not available for " + + quorumMember.getString("quorum_did") + ". Please initate sync command"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + + String quorumPubKeyStr = IPFSNetwork.get(QuorumPublicKeyIpfsHash, ipfs); // get quorum + // member's + // public key + // from + // ipfs. + String pubKeyAlgo = publicKeyAlgStr(quorumPubKeyStr); + + JSONObject detailsForVerify = new JSONObject(); + detailsForVerify.put("did", quorumMember.getString("quorum_did")); + detailsForVerify.put("hash", quorumHash); + detailsForVerify.put("signature", quorumMember.getString("quorumPrivateShareSign")); + + boolean val = ((verifySignature(quorumsPrivateShareSign, + getPubKeyFromStr(quorumPubKeyStr, pubKeyAlgo), quorumsPrivateKeySign, pubKeyAlgo)) + && (Authenticate.verifySignature(detailsForVerify.toString()))); + if (val) { + quorumSignVerifyCount++; + RecipientLogger + .debug("Quorum member " + quorumMember.getString("quorum_did") + " verified."); + } + } + RecipientLogger.debug("Verified Quorum Count " + quorumSignVerifyCount); + yesQuorum = quorumSignVerifyCount >= quorumSignatures.length(); + } + +// RecipientLogger.debug("Hash to verify Sender: " + hash); + JSONObject detailsForVerify = new JSONObject(); + detailsForVerify.put("did", senderDidIpfsHash); + detailsForVerify.put("hash", hash); + detailsForVerify.put("signature", senderPvtShareBits); + + boolean yesSender = false; + + String senderPublicKeyIpfsHash = getPubKeyIpfsHash_DIDserver(senderDidIpfsHash, 1); // get public + // key + // ipfs hash of + // the + // sender. + + if (senderPublicKeyIpfsHash.isEmpty()) { + output.println("433"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", tid); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender data not available for " + senderDidIpfsHash); + RecipientLogger.info("Sender's public key data not available for " + senderDidIpfsHash + + ". Please initate sync command"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + + String senderPubKeyStr = IPFSNetwork.get(senderPublicKeyIpfsHash, ipfs); // get sender's public key + // from + // ipfs. + + String pubKeyAlgo = publicKeyAlgStr(senderPubKeyStr); + + // verifySignature uses sender's public key to verify the private key signature. + // if(verifySignature(senderPvtShareBits,getPubKeyFromStr(senderPubKeyStr,pubKeyAlgo),senderSignature,pubKeyAlgo)==true) + + // { + yesSender = Authenticate.verifySignature(detailsForVerify.toString()); + // } + +// RecipientLogger.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"); + RecipientLogger.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); + RecipientLogger.debug("Sender and Quorum Verified"); + output.println("200"); + + // To accecpt sender req for new Token chain block, and provide the same + String request; + try { + request = input.readLine(); + } catch (SocketException e) { + RecipientLogger.warn( + "Sender Stream Null, receiver unable to accept senders request to get new Token chain block for hashing"); + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Sender Stream Null, receiver unable to accept senders request to get new Token chain block for hashing"); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + + 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); + 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); + } + + 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); + } + + 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)); + + JSONObject lastObject = new JSONObject(); + + JSONArray lastObjectArray = new JSONArray(); + if (request.equals("Request for new blocks being added to the Token Chains")) { + + RecipientLogger.debug("Request for new blocks being added to the Token Chains"); + + // TODO +// RecipientLogger.debug("intPart: " + intPart); + 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 arr = new JSONArray(wholeTokenChainContent.get(i)); + + lastObject.put("sender", senderDidIpfsHash); + lastObject.put("group", allTokens); + lastObject.put("comment", comment); + lastObject.put("tid", tid); + lastObject.put("receiver", receiverDidIpfsHash); + lastObject.put("pledgeToken", ""); + lastObject.put("tokensPledgedFor", allTokens); + lastObject.put("tokensPledgedWith", pledgedDetails); + lastObject.put("distributedObject", distributedObject); + + if (!BlockHash.isEmpty()) { + lastObject.put("blockHash", BlockHash); + } + + arr.put(lastObject); + + WholeTokenChainsWithAppendedBlock.add(arr.toString()); + + JSONObject tokenLastObject = new JSONObject(); + tokenLastObject.put("token", wholeTokens.getString(i)); + tokenLastObject.put("lastObject", lastObject); + lastObjectArray.put(tokenLastObject); + } + + } + output.println(lastObjectArray.toString()); + + String hashAndSignsforTokenChains; + try { + hashAndSignsforTokenChains = input.readLine(); + + if (hashAndSignsforTokenChains.contains("Token chains Not Matching")) { + RecipientLogger.warn("Token chains Not Matching"); + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Token chains Not Matching"); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + + hash_Signs_ForTokenChains = new JSONArray(hashAndSignsforTokenChains); + } catch (SocketException e) { + RecipientLogger.warn("Sender Stream Null - Token Chain Updation status"); + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender Stream Null - Token Chain Updation Status"); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + + JSONObject parttokenchainsToBeHashed = new JSONObject(); + + // TODO + 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 tokens = partTokens.getString(i); + String hashString = tokens.concat(receiverDidIpfsHash); + String hashForPositions = calculateHash(hashString, "SHA3-256"); + + JSONObject newPartObject = new JSONObject(); + newPartObject.put("sender", senderDidIpfsHash); + newPartObject.put("receiver", receiverDidIpfsHash); + newPartObject.put("comment", comment); + newPartObject.put("tid", tid); + newPartObject.put("pledgeToken", ""); + newPartObject.put("tokensPledgedFor", allTokens); + newPartObject.put("tokensPledgedWith", pledgedDetails); + newPartObject.put("distributedObject", distributedObject); + + newPartObject.put("amount", partAmount); + newPartObject.put("cheque", chequeHash); + newPartObject.put("role", "Receiver"); + + JSONArray partTokenChainContentArray = partTokenChainContent.getJSONArray(i); + + 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); + JSONArray chainArray = new JSONArray(); + for (int j = 0; j < readChainArray.length(); j++) { + + JSONObject object = readChainArray.getJSONObject(j); + + if (object.has("nextHash") && object.has("previousHash")) { + object.remove("nextHash"); + object.remove("previousHash"); + } + + chainArray.put(object); + + } + + chainArray.put( + partTokenChainContentArray.getJSONObject(partTokenChainContentArray.length() - 1)); + chainArray.put(newPartObject); + parttokenchainsToBeHashed.put(partTokens.getString(i), chainArray); + final_parttokenchains.put(partTokens.getString(i), chainArray); + + } else { + + partTokenChainContentArray.put(newPartObject); + + parttokenchainsToBeHashed.put(partTokens.getString(i), partTokenChainContentArray); + final_parttokenchains.put(partTokens.getString(i), partTokenChainContentArray); + + } + } + + String pinDetails; + try { + pinDetails = input.readLine(); + } catch (SocketException e) { + RecipientLogger.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")) { + + + String essentialShare; + try { + essentialShare = input.readLine(); + } catch (SocketException e) { + RecipientLogger.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(); + + // Writing Whole and part token chains to receiver's local storage. + for (int i = 0; i < intPart; i++) { + + String tokenChainContent_WithoutHashAndSign = WholeTokenChainsWithAppendedBlock.get(i); + JSONArray tokenChain = new JSONArray(tokenChainContent_WithoutHashAndSign); + + JSONObject lastObj = new JSONObject(); + lastObj = tokenChain.getJSONObject(tokenChain.length() - 1); + tokenChain.remove(tokenChain.length() - 1); + lastObj.put("hash", hash_Signs_ForTokenChains.getJSONObject(i).getString("hash")); + lastObj.put("pvtShareBits", + hash_Signs_ForTokenChains.getJSONObject(i).getString("pvtShareBits")); + tokenChain.put(lastObj); + writeToFile(TOKENCHAIN_PATH + wholeTokens.getString(i) + ".json", tokenChain.toString(), + false); + } + + for (int i = 0; i < partTokens.length(); i++) { + + JSONArray finalPartTokenChain = final_parttokenchains.getJSONArray(partTokens.getString(i)); + + writeToFile(PART_TOKEN_CHAIN_PATH + partTokens.getString(i) + ".json", + finalPartTokenChain.toString(), false); + } + + JSONObject transactionRecord = new JSONObject(); + transactionRecord.put("role", "Receiver"); + transactionRecord.put("tokens", allTokens); + transactionRecord.put("txn", tid); + transactionRecord.put("quorumList", quorumSignatures); + 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); + + output.println("Send Response"); + +// RecipientLogger.debug("!@#$% 1"); + + // Updating the sender's part token chains with the chains hash and receivers + // sign. + + if (decimalPart != 0.0) { + String parttokenchains_req; + try { + parttokenchains_req = input.readLine(); + + } catch (SocketException e) { + + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Part token chain hashing req not received."); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + + // TokenReceiverLogger.debug("!@#$% 2: " + parttokenchains_req); + + if (parttokenchains_req.equals("New part token chain to be hashed")) { + String PartTokenChainToBeHashed_1_string; + + try { + PartTokenChainToBeHashed_1_string = input.readLine(); + + } catch (SocketException e) { + + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Receiver not ale to hash part token chains for the sender."); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + + // TokenReceiverLogger.debug("!@#$% 3: " + PartTokenChainToBeHashed_1_string); + + JSONArray partTokenChainToBeHashed = new JSONArray(PartTokenChainToBeHashed_1_string); + + String hashForChain = calculateHash(partTokenChainToBeHashed.toString(), "SHA3-256"); + + String hashSignedwithPvtShare = getSignFromShares(pvt, hashForChain); + + JSONObject obj = partTokenChainToBeHashed + .getJSONObject(partTokenChainToBeHashed.length() - 1); + partTokenChainToBeHashed.remove(partTokenChainToBeHashed.length() - 1); + obj.put("hash", hashForChain); + obj.put("pvtShareBits", hashSignedwithPvtShare); + + partTokenChainToBeHashed.put(obj); + + output.println(partTokenChainToBeHashed.toString()); + + // TokenReceiverLogger.debug("!@#$% 4: " + partTokenChainToBeHashed); + + } + + if (parttokenchains_req.equals("Old part token chains to be hashed")) { + + String PartTokenChainToBeHashed_2_string; + + try { + PartTokenChainToBeHashed_2_string = input.readLine(); + + } catch (SocketException e) { + + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Receiver not ale to hash part token chains for the sender."); + + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + + } + // TokenReceiverLogger.debug("!@#$% 5: " + PartTokenChainToBeHashed_2_string); + + JSONObject PartTokenChainsToBeHashed = new JSONObject( + PartTokenChainToBeHashed_2_string); + + JSONObject hashedAndSigned_partTokenChains = new JSONObject(); + + for (int i = 0; i < partTokens.length(); i++) { + + JSONArray parttokenChain = PartTokenChainsToBeHashed + .getJSONArray(partTokens.getString(i)); + + String hashForChain2 = calculateHash(parttokenChain.toString(), "SHA3-256"); + + String hashSignedwithPvtShare2 = getSignFromShares(pvt, hashForChain2); + + JSONObject obj2 = parttokenChain.getJSONObject(parttokenChain.length() - 1); + parttokenChain.remove(parttokenChain.length() - 1); + obj2.put("hash", hashForChain2); + obj2.put("pvtShareBits", hashSignedwithPvtShare2); + + parttokenChain.put(obj2); + + hashedAndSigned_partTokenChains.put(partTokens.getString(i), parttokenChain); + } + + output.println(hashedAndSigned_partTokenChains.toString()); + + // TokenReceiverLogger.debug("!@#$% 6: " + hashedAndSigned_partTokenChains); + + } + } + + RecipientLogger.info("Transaction ID: " + tid + "Transaction Successful"); + 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"); + RecipientLogger.info(" Transaction Successful"); + 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"); + RecipientLogger.info(" Transaction failed - Failed to unpin"); + 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"); + RecipientLogger.info(" Transaction failed - Sender side consensus failed"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + APIResponse.put("did", ""); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Unidentified message request"); + RecipientLogger.info(" Transaction failed - unidentified message request"); + 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); + RecipientLogger.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); + RecipientLogger.error("Exception Occurred", e); + } + + } + } +} \ No newline at end of file diff --git a/src/com/rubix/ConvinientTransfers/Sender.java b/src/com/rubix/ConvinientTransfers/Sender.java new file mode 100644 index 00000000..d22d33cd --- /dev/null +++ b/src/com/rubix/ConvinientTransfers/Sender.java @@ -0,0 +1,1839 @@ +package com.rubix.ConvinientTransfers; + +import com.rubix.Consensus.InitiatorConsensus; +import com.rubix.Consensus.InitiatorProcedure; +import com.rubix.Resources.Functions; +import com.rubix.Resources.IPFSNetwork; +import com.rubix.TokenTransfer.TransferPledge.Initiator; +import com.rubix.TokenTransfer.TransferPledge.Unpledge; + +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 java.net.Socket; +import java.net.SocketException; +import java.net.URL; +import java.net.UnknownHostException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static com.rubix.NFTResources.NFTFunctions.*; +import static com.rubix.Resources.Functions.*; +import static com.rubix.Resources.IPFSNetwork.*; + +public class Sender { + private static final Logger SenderLogger = Logger.getLogger(Sender.class); + public static BufferedReader serverInput; + private static JSONObject detailsObject = new JSONObject(); + private static JSONArray quorumArray = new JSONArray(); + public static String tid = null; + private static JSONArray partTokens = new JSONArray(); + private static JSONArray wholeTokens = new JSONArray(); + private static ArrayList alphaPeersList; + private static ArrayList betaPeersList; + private static ArrayList gammaPeersList; + private static int alphaSize = -1; + private static JSONArray tokenPreviousSender = new JSONArray(); + private static JSONArray wholeTokenChainHash = new JSONArray(); + private static JSONArray partTokenChainHash = new JSONArray(); + public static JSONArray lastObJsonArray = new JSONArray(); + private static JSONObject partTokenChainsPrevState = new JSONObject(); + private static String tokenChainPath = "", tokenPath = ""; + private static JSONObject amountLedger = new JSONObject(); + private static JSONArray allTokens = new JSONArray(); + private static boolean newPart = false, oldNew = false; + private static Double decimalAmount = -1.00; + private static String PART_TOKEN_CHAIN_PATH = TOKENCHAIN_PATH.concat("PARTS/"); + private static String PART_TOKEN_PATH = TOKENS_PATH.concat("PARTS/"); + private static String senderPayloadHash = null; + private static int intPart = -1; + private static int wholeAmount = -1; + private static PrintStream output; + private static BufferedReader input; + private static Socket senderSocket; + private static boolean senderMutex = false; + public static String authSenderByRecHash; + public static JSONObject partTokenChainArrays = new JSONObject(); + public static String senderPayloadSign = null; + + public static void resetVariables() { + detailsObject = new JSONObject(); + quorumArray = new JSONArray(); + tid = null; + partTokens = new JSONArray(); + wholeTokens = new JSONArray(); + alphaPeersList = new ArrayList<>(); + betaPeersList = new ArrayList<>(); + gammaPeersList = new ArrayList<>(); + alphaSize = -1; + tokenPreviousSender = new JSONArray(); + wholeTokenChainHash = new JSONArray(); + partTokenChainHash = new JSONArray(); + lastObJsonArray = new JSONArray(); + partTokenChainsPrevState = new JSONObject(); + tokenChainPath = ""; + tokenPath = ""; + amountLedger = new JSONObject(); + allTokens = new JSONArray(); + newPart = false; + oldNew = false; + decimalAmount = -1.00; + PART_TOKEN_CHAIN_PATH = TOKENCHAIN_PATH.concat("PARTS/"); + PART_TOKEN_PATH = TOKENS_PATH.concat("PARTS/"); + senderPayloadHash = null; + intPart = -1; + wholeAmount = -1; + senderMutex = false; + authSenderByRecHash = ""; + SenderLogger.debug("Cleanup completed"); + partTokenChainArrays = new JSONObject(); + senderPayloadSign = null; + } + + /** + * A sender node to transfer tokens + * + * @param data Details required for tokenTransfer + * @param ipfs IPFS instance + * @param port Sender port for communication + * @return Transaction Details (JSONObject) + * @throws IOException handles IO Exceptions + * @throws JSONException handles JSON Exceptions + * @throws NoSuchAlgorithmException handles No Such Algorithm Exceptions + */ + public static JSONObject SendPartA(String data, IPFS ipfs, int port) + throws JSONException, IOException, Exception, UnknownHostException { + repo(ipfs); + resetVariables(); + JSONObject APIResponse = new JSONObject(); + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + SenderLogger.debug("Transfer Part A"); + + JSONObject challengeObject = new JSONObject(); + + detailsObject = new JSONObject(data); + String receiverDidIpfsHash = detailsObject.getString("receiverDidIpfsHash"); + String receiverPeerId = getValues(DATA_PATH + "DataTable.json", "peerid", "didHash", receiverDidIpfsHash); + syncDataTableByDID(receiverDidIpfsHash); + String pvt = detailsObject.getString("pvt"); + double requestedAmount = detailsObject.getDouble("amount"); + int type = detailsObject.getInt("type"); + String comment = detailsObject.getString("comment"); + String keyPass = detailsObject.getString("pvtKeyPass"); + PrivateKey pvtKey = null; + pvtKey = getPvtKey(keyPass, 1); + + // If user enters wrong pvt key password + if (pvtKey == null) { + APIResponse.put("message", + "Incorrect password entered for Private Key, cannot proceed with the transaction"); + SenderLogger.warn("Incorrect Private Key password entered"); + return APIResponse; + } + + // detailsObject.remove("pvtKeyPass"); + + APIResponse = new JSONObject(); + + intPart = (int) requestedAmount; + String senderPeerID = getPeerID(DATA_PATH + "DID.json"); + String senderDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", senderPeerID); + + if (senderMutex) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender busy. Try again later"); + SenderLogger.warn("Sender busy"); + return APIResponse; + } + + senderMutex = true; + + 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); + } + +// SenderLogger.debug("Requested Part: " + requestedAmount); // 2 +// SenderLogger.debug("Int Part: " + intPart); // 2 + String bankFile = readFile(PAYMENTS_PATH.concat("BNK00.json")); + JSONArray bankArray = new JSONArray(bankFile); // 18 + + // wholeAmount =2 ; + if (intPart <= bankArray.length()) + wholeAmount = intPart; + else + wholeAmount = bankArray.length(); + + for (int i = 0; i < wholeAmount; i++) { + wholeTokens.put(bankArray.getJSONObject(i).getString("tokenHash")); // 2 + } + + // TokenSenderLogger.debug("wholeTokens is "+wholeTokens.toString()); + + // TokenSenderLogger.debug("wholeTokens length is "+wholeTokens.length()); + for (int i = 0; i < wholeTokens.length(); i++) { // 2 + String tokenRemove = wholeTokens.getString(i); + for (int j = 0; j < bankArray.length(); j++) { + if (bankArray.getJSONObject(j).getString("tokenHash").equals(tokenRemove)) + bankArray.remove(j); + } + } + + 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"); + if (!(token.exists() && tokenchain.exists())) { + SenderLogger.info("Token files not available"); + senderMutex = false; + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Invalid token(s)"); + return APIResponse; + + } + String wholeTokenHash = add(TOKENS_PATH + wholeTokens.get(i), ipfs); + pin(wholeTokenHash, ipfs); + 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(); + + if (tokenChainFileArray.length() > 0) { + // JSONObject lastObject = + // tokenChainFileArray.getJSONObject(tokenChainFileArray.length() - 1); + + for (int j = 0; j < tokenChainFileArray.length(); j++) { + +// TokenSenderLogger.debug("Reading token chain block = "+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); + + } + + decimalAmount = requestedAmount - wholeAmount; + decimalAmount = formatAmount(decimalAmount); + +// SenderLogger.debug("Decimal Part: " + decimalAmount); + if (decimalAmount > 0.000D) { +// SenderLogger.debug("Decimal Amount > 0.000D"); + String partFileContent = readFile(partTokensFile.toString()); + JSONArray partContentArray = new JSONArray(partFileContent); + + if (partContentArray.length() == 0) { + newPart = true; + String chosenToken = bankArray.getJSONObject(0).getString("tokenHash"); + partTokens.put(chosenToken); + amountLedger.put(chosenToken, formatAmount(decimalAmount)); + + } else { + Double counter = decimalAmount; + JSONArray selectParts = new JSONArray(partFileContent); + while (counter > 0.000D) { + counter = formatAmount(counter); + if (!(selectParts.length() == 0)) { +// SenderLogger.debug("Old Parts"); + String currentPartToken = selectParts.getJSONObject(0).getString("tokenHash"); + Double currentPartBalance = partTokenBalance(currentPartToken); + currentPartBalance = formatAmount(currentPartBalance); + if (counter >= currentPartBalance) + amountLedger.put(currentPartToken, formatAmount(currentPartBalance)); + else + amountLedger.put(currentPartToken, formatAmount(counter)); + + partTokens.put(currentPartToken); + counter -= currentPartBalance; + selectParts.remove(0); + } else { + oldNew = true; + String chosenToken = bankArray.getJSONObject(0).getString("tokenHash"); + partTokens.put(chosenToken); + amountLedger.put(chosenToken, formatAmount(counter)); + File tokenFile = new File(TOKENS_PATH.concat(chosenToken)); + tokenFile.renameTo(new File(PART_TOKEN_PATH.concat(chosenToken))); + 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); + } else { + String shiftedContent = readFile(PAYMENTS_PATH.concat("ShiftedTokens.json")); + JSONArray shiftedArray = new JSONArray(shiftedContent); + shiftedArray.put(chosenToken); + writeToFile(PAYMENTS_PATH.concat("ShiftedTokens.json"), shiftedArray.toString(), false); + } + counter = 0.000D; + } + } + } + } + + if (newPart) { + tokenChainPath = TOKENCHAIN_PATH; + tokenPath = TOKENS_PATH; + } else { + tokenChainPath = TOKENCHAIN_PATH.concat("PARTS/"); + tokenPath = TOKENS_PATH.concat("PARTS/"); + } + + for (int i = 0; i < partTokens.length(); i++) { + File token = new File(tokenPath.concat(partTokens.getString(i))); + File tokenchain = new File(tokenChainPath.concat(partTokens.getString(i)) + ".json"); + if (!(token.exists() && tokenchain.exists())) { + if (!token.exists()) + SenderLogger.debug("Token File for parts not available"); + if (!tokenchain.exists()) + SenderLogger.debug("Token Chain File for parts not available"); + + SenderLogger.info("Tokens Files Missing"); + senderMutex = false; + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Invalid part token(s)"); + return APIResponse; + + } + 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); + for (int j = 0; j < finalChainArray.length(); j++) { + JSONObject object = finalChainArray.getJSONObject(j); + /* + * if (finalChainArray.length() == 1) { object.put("previousHash", ""); + * object.put("nextHash", ""); } else if (finalChainArray.length() > 1) { if (j + * == 0) { object.put("previousHash", ""); 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("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")); } } + */ + + if (object.has("nextHash") && object.has("previousHash")) { + object.remove("nextHash"); + object.remove("previousHash"); + } + + chainArray.put(object); + + } + + partTokenChainsPrevState.put(partTokens.getString(i), chainArray); + // TokenSenderLogger.debug("Part token chain to be sent for verification: + // "+prevStateChainContent); + + writeToFile(tokenChainPath.concat(partTokens.getString(i)).concat(".json"), chainArray.toString(), false); + + partTokenChainHash.put(add(tokenChainPath.concat(partTokens.getString(i)).concat(".json"), ipfs)); + } + SenderLogger.debug("Completed tokens selection"); + + authSenderByRecHash = calculateHash( + wholeTokens.toString() + wholeTokenChainHash.toString() + partTokens.toString() + + partTokenChainHash.toString() + receiverDidIpfsHash + senderDidIpfsHash + comment, + "SHA3-256"); + // TokenSenderLogger.debug("Hash to verify Sender: " + authSenderByRecHash); + tid = calculateHash(authSenderByRecHash, "SHA3-256"); + + challengeObject.put("authSenderByRecHash", authSenderByRecHash); + + 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)); + +// boolean sanityCheck = sanityCheck("Receiver", receiverPeerId, ipfs, port + 10); + boolean sanityCheck = true; + if (!sanityCheck) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", sanityMessage); + // TokenSenderLogger.warn(sanityMessage); + senderMutex = false; + return APIResponse; + } + + syncDataTable(receiverDidIpfsHash, null); + + if (!receiverPeerId.equals("")) { + swarmConnectP2P(receiverPeerId, ipfs); + SenderLogger.debug("Swarm connected with " + receiverPeerId); + } else { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver Peer ID null"); + SenderLogger.warn("Receiver Peer ID null"); + senderMutex = false; + return APIResponse; + } + + String receiverWidIpfsHash = getValues(DATA_PATH + "DataTable.json", "walletHash", "didHash", + receiverDidIpfsHash); + if (!receiverWidIpfsHash.equals("")) { + nodeData(receiverDidIpfsHash, receiverWidIpfsHash, ipfs); + } else { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver WID null"); + SenderLogger.warn("Receiver WID null"); + senderMutex = false; + return APIResponse; + } + + JSONArray alphaQuorum = new JSONArray(); + + switch (type) { + case 1: { + + quorumArray = getQuorum(senderDidIpfsHash, receiverDidIpfsHash, allTokens.length()); + break; + } + + case 2: { + File quorumFile = new File(DATA_PATH.concat("quorumlist.json")); + if (!quorumFile.exists()) { + SenderLogger.error("Quorum List for Subnet not found"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Quorum List for Subnet not found"); + return APIResponse; + } else { + String quorumList = readFile(DATA_PATH + "quorumlist.json"); + if (quorumList != null) { + quorumArray = new JSONArray(readFile(DATA_PATH + "quorumlist.json")); + } else { + SenderLogger.error("File for Quorum List for Subnet is empty"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "File for Quorum List for Subnet is empty"); + return APIResponse; + } + + } + + break; + } + case 3: { + quorumArray = detailsObject.getJSONArray("quorum"); + break; + } + default: { + SenderLogger.error("Unknown quorum type input, cancelling transaction"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Unknown quorum type input, cancelling transaction"); + return APIResponse; + + } + } + + if (quorumArray.length() > 7) { + quorumArray = cleanQuorum(quorumArray, senderDidIpfsHash, receiverDidIpfsHash, 7); + } + + String errMessage = null; + for (int i = 0; i < quorumArray.length(); i++) { + + if (quorumArray.get(i).equals(senderDidIpfsHash)) { + SenderLogger.error("SenderDID " + senderDidIpfsHash + " cannot be a Quorum"); + errMessage = "SenderDID " + senderDidIpfsHash; + } + if (quorumArray.get(i).equals(receiverDidIpfsHash)) { + SenderLogger.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; + } + + } + +// //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 + 10); + boolean quorumSanityCheck = true; + + if (!quorumSanityCheck) { + sanityFailedQuorum.put(quorumPeerID); + if (i <= 6) + alphaCheck++; + } + } + + if (alphaCheck > 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)); +// SenderLogger.warn("Quorum: ".concat(message.concat(sanityMessage))); + return APIResponse; + } +// //sanity check for Quorum - Ends + long startTime, endTime, totalTime; + + QuorumSwarmConnect(quorumArray, ipfs); + + alphaSize = quorumArray.length(); + + for (int i = 0; i < alphaSize; i++) + alphaQuorum.put(quorumArray.getString(i)); + + startTime = System.currentTimeMillis(); + + alphaPeersList = QuorumCheck(alphaQuorum, alphaSize); + + endTime = System.currentTimeMillis(); + totalTime = endTime - startTime; +// eventLogger.debug("Quorum Check " + totalTime); + + if (alphaPeersList.size() < minQuorum(alphaSize)) { + updateQuorum(quorumArray, null, false, type); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Quorum Members not available"); + SenderLogger.warn("Quorum Members not available"); + senderMutex = false; + return APIResponse; + } + +// SenderLogger.debug("Final Selected Alpha Members: " + alphaPeersList); + JSONArray alphaList = new JSONArray(); + for (int i = 0; i < alphaPeersList.size(); i++) { + alphaList.put(alphaPeersList.get(i)); + } + + int numberOfTokensToPledge = 0; + if (wholeAmount > 0) { + numberOfTokensToPledge += wholeAmount; + if (decimalAmount > 0) + numberOfTokensToPledge += 1; + } else + numberOfTokensToPledge = 1; +// +// SenderLogger.debug("Amount being transferred: " + requestedAmount +// + " and number of tokens required to be pledged: " + numberOfTokensToPledge); + + JSONObject dataToSendToInitiator = new JSONObject(); + dataToSendToInitiator.put("alphaList", alphaList); + dataToSendToInitiator.put("tokenList", wholeTokens); + dataToSendToInitiator.put("amount", numberOfTokensToPledge); + dataToSendToInitiator.put("tid", tid); + dataToSendToInitiator.put("pvt", pvt); + dataToSendToInitiator.put("pvtKeyPass", keyPass); + dataToSendToInitiator.put("sender", senderDidIpfsHash); + dataToSendToInitiator.put("receiver", receiverDidIpfsHash); + + // TokenSenderLogger.debug("Details being sent to Initiator: " + + // dataToSendToInitiator); + + boolean abort = Initiator.pledgeSetUp(dataToSendToInitiator.toString(), ipfs, 22143); + if (abort) { + Initiator.abort = false; + updateQuorum(quorumArray, null, false, type); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + if (Initiator.abortReason.has("Quorum")) + APIResponse.put("message", "Alpha Node " + Initiator.abortReason.getString("Quorum") + " " + + Initiator.abortReason.getString("Reason")); + else + APIResponse.put("message", Initiator.abortReason.getString("Reason")); + SenderLogger.warn("Quorum Members with insufficient Tokens/Credits"); + senderMutex = false; + Initiator.abortReason = new JSONObject(); + return APIResponse; + } else { + JSONArray array = Initiator.quorumWithHashesArray; + challengeObject.put("pledgeDetails", array); + + } + +// SenderLogger.debug("Nodes that pledged tokens: " + Initiator.pledgedNodes); + + /** + * Send the array without sender sign calculated + */ + JSONArray newChains = new JSONArray(); + for (int i = 0; i < intPart; i++) { + JSONObject lastObject = new JSONObject(); + // lastObject.put("senderSign", ""); + lastObject.put("sender", senderDidIpfsHash); + lastObject.put("group", allTokens); + lastObject.put("comment", comment); + lastObject.put("tid", tid); + lastObject.put("receiver", receiverDidIpfsHash); + lastObject.put("pledgeToken", ""); + lastObject.put("tokensPledgedFor", allTokens); + lastObject.put("tokensPledgedWith", Initiator.pledgedTokensArray); + lastObject.put("distributedObject", Initiator.distributedObject); + + String tokenChainFileContent = readFile(TOKENCHAIN_PATH + wholeTokens.get(i) + ".json"); + JSONArray tokenChain = new JSONArray(tokenChainFileContent); + tokenChain.put(lastObject); + lastObJsonArray.put(lastObject); + + String tokenChainHash = calculateHash(tokenChain.toString(), "SHA3-256"); + JSONObject tokenObject = new JSONObject(); + tokenObject.put("token", wholeTokens.getString(i)); + tokenObject.put("hash", tokenChainHash); + newChains.put(tokenObject); + } + challengeObject.put("lastObject", newChains); + senderPayloadHash = calculateHash(allTokens.toString() + senderDidIpfsHash + comment, "SHA3-256"); + + challengeObject.put("senderPayloadSign", senderPayloadHash); + + FileWriter file = new FileWriter(WALLET_DATA_PATH.concat("/ChallengePayload").concat(tid).concat(".json")); + file.write(challengeObject.toString()); + file.close(); + + JSONArray signedChains = new JSONArray(); + JSONObject payloadSigned = new JSONObject(); + File privateShareFile = new File(DATA_PATH.concat(senderDidIpfsHash).concat("/PrivateShare.png")); + + if (privateShareFile.exists()) { + senderPayloadSign = getSignFromShares(pvt, senderPayloadHash); + payloadSigned.put("authSenderByRecHash", getSignFromShares(pvt, authSenderByRecHash)); + payloadSigned.put("senderPayloadSign", senderPayloadSign); + for (int i = 0; i < intPart; i++) { + JSONObject tokenObject = newChains.getJSONObject(i); + // JSONArray chainArray = tokenObject.getJSONArray("chain"); + // JSONObject lastObject = chainArray.getJSONObject(chainArray.length() - 1); + // String senderSign = getSignFromShares(pvt, authSenderByRecHash); + // lastObject.put("senderSign", senderSign); + + // chainArray.remove(chainArray.length() - 1); + // chainArray.put(lastObject); + + // String chainHash = calculateHash(chainArray.toString(), "SHA3-256"); + String chainSign = getSignFromShares(pvt, newChains.getJSONObject(i).getString("hash")); + tokenObject.put("chainSign", chainSign); + signedChains.put(tokenObject); + } + payloadSigned.put("lastObject", signedChains); + + FileWriter payloadfile = new FileWriter( + WALLET_DATA_PATH.concat("/SignPayload").concat(tid).concat(".json")); + payloadfile.write(payloadSigned.toString()); + payloadfile.close(); + + JSONArray quorumWithSignsArray = new JSONArray(); + JSONArray pledgeArray = Initiator.quorumWithHashesArray; + if (pledgeArray.length() == 0) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Not enough token to pledge"); + SenderLogger.warn("Pledging failed"); + return APIResponse; + } + + // TokenSenderLogger.debug("pledge object is " + pledgeArray.toString()); + + for (int i = 0; i < Initiator.quorumWithHashesArray.length(); i++) { + JSONObject jsonObject = Initiator.quorumWithHashesArray.getJSONObject(i); + Iterator keys = jsonObject.keys(); + // TokenSenderLogger.debug("jsonObject is " + jsonObject.toString()); + JSONObject pledgeSignedObject = new JSONObject(); + String key = ""; + JSONArray hashAndSignsArray = new JSONArray(); + while (keys.hasNext()) { + key = keys.next(); + if (jsonObject.get(key) instanceof JSONArray) { + // do something with jsonObject here + + JSONArray hashArray = new JSONArray(jsonObject.get(key).toString()); + for (int j = 0; j < hashArray.length(); j++) { + String sign = getSignFromShares(pvt, hashArray.get(j).toString()); + pledgeSignedObject.put("hash", hashArray.get(j)); + pledgeSignedObject.put("sign", sign); + hashAndSignsArray.put(pledgeSignedObject); + } + } + } + JSONObject signObject = new JSONObject(); + signObject.put(key, hashAndSignsArray); + // TokenSenderLogger.debug("signObject is " + signObject); + quorumWithSignsArray.put(signObject); + + } + + payloadSigned.put("pledgeDetails", quorumWithSignsArray); + // TokenSenderLogger.debug("pledgeDetails: " + quorumWithSignsArray); + + FileWriter spfile = new FileWriter(WALLET_DATA_PATH.concat("/signedPayload").concat(tid).concat(".json")); + spfile.write(payloadSigned.toString()); + spfile.close(); + + senderMutex = false; + return SendPartB(payloadSigned, ipfs, port); + } + senderMutex = false; + return challengeObject; + } + + public static JSONObject SendPartB(JSONObject signPayload, IPFS ipfs, int port) + throws JSONException, IOException, InterruptedException, ParseException, Exception { + + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + SenderLogger.debug("Transfer Part B"); + + String senderSign = signPayload.getString("authSenderByRecHash"); + JSONObject APIResponse = new JSONObject(); + String receiverDidIpfsHash = detailsObject.getString("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"); + String keyPass = detailsObject.getString("pvtKeyPass"); + + PrivateKey pvtKey = getPvtKey(keyPass, 1); + String senderPeerID = getPeerID(DATA_PATH + "DID.json"); + String senderDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", senderPeerID); + JSONArray quorumWithSignsArray = signPayload.getJSONArray("pledgeDetails"); + JSONArray signedChains = signPayload.getJSONArray("lastObject"); + + // If user enters wrong pvt key password + if (pvtKey == null) { + APIResponse.put("message", + "Incorrect password entered for Private Key, cannot proceed with the transaction"); + SenderLogger.warn("Incorrect Private Key password entered"); + return APIResponse; + } + + SenderLogger.debug("Sender IPFS forwarding to DID: " + receiverDidIpfsHash + " PeerID: " + receiverPeerId); + forward(receiverPeerId.concat("step"), port, receiverPeerId); + SenderLogger.debug("Forwarded to " + receiverPeerId + " on " + port); + senderSocket = new Socket("127.0.0.1", port); + + input = new BufferedReader(new InputStreamReader(senderSocket.getInputStream())); + output = new PrintStream(senderSocket.getOutputStream()); + + long startTime = System.currentTimeMillis(); + + /** + * Sending Sender Peer ID to Receiver Receiver to authenticate Sender's DID + * (Identity) + */ + output.println("PartB"); + output.println(senderPeerID); + SenderLogger.debug("Sent PeerID"); + + String peerAuth; + try { + peerAuth = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Sender Auth"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "is unable to respond! - Sender Auth"); + + return APIResponse; + } + + if (peerAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.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; + + } else if (peerAuth != null && (!peerAuth.equals("200"))) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.info("Sender Data Not Available"); + 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 Data Not Available"); + return APIResponse; + + } + + String pvtKeyType = privateKeyAlgorithm(1); + // String senderSignWithPvtKey = pvtKeySign(senderSign, pvtKey, pvtKeyType); + + for (int i = 0; i < partTokens.length(); i++) { + String chainContent = readFile(tokenChainPath.concat(partTokens.getString(i)).concat(".json")); + JSONArray chainArray = new JSONArray(chainContent); + JSONObject newLastObject = new JSONObject(); + /* + * if (chainArray.length() == 0) { newLastObject.put("previousHash", ""); + * + * } 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")); } + */ + + Double amount = formatAmount(amountLedger.getDouble(partTokens.getString(i))); + + newLastObject.put("senderSign", senderSign); + newLastObject.put("sender", senderDidIpfsHash); + newLastObject.put("receiver", receiverDidIpfsHash); + newLastObject.put("comment", comment); + newLastObject.put("tid", tid); + newLastObject.put("role", "Sender"); + newLastObject.put("amount", amount); + chainArray.put(newLastObject); + partTokenChainArrays.put(partTokens.getString(i), chainArray); + + } + JSONArray proofOfWork = new JSONArray(); + for (int i = 0; i < wholeTokens.length(); i++) { + File proofFile = new File(TOKENCHAIN_PATH + "Proof/" + wholeTokens.getString(i) + ".proof"); + if (proofFile.exists()) { + String proofCID = add(TOKENCHAIN_PATH + "Proof/" + wholeTokens.getString(i) + ".proof", ipfs); + JSONObject proofObject = new JSONObject(); + proofObject.put("token", wholeTokens.getString(i)); + proofObject.put("cid", proofCID); + proofOfWork.put(proofObject); + } + } + JSONObject tokenDetails = new JSONObject(); + tokenDetails.put("whole-tokens", wholeTokens); + tokenDetails.put("whole-tokenChains", wholeTokenChainHash); + tokenDetails.put("hashSender", partTokenChainHash); + tokenDetails.put("part-tokens", partTokens); + tokenDetails.put("part-tokenChains", partTokenChainArrays); + tokenDetails.put("part-tokenChains-PrevState", partTokenChainsPrevState); + tokenDetails.put("sender", senderDidIpfsHash); + tokenDetails.put("proof", proofOfWork); + tokenDetails.put("distributedObject", Initiator.distributedObject); + String doubleSpendString = tokenDetails.toString(); + + // TokenSenderLogger.debug("tokenDetails is "+tokenDetails.toString()); + + String doubleSpend = calculateHash(doubleSpendString, "SHA3-256"); + writeToFile(LOGGER_PATH + "doubleSpend", doubleSpend, false); +// SenderLogger.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("amount", requestedAmount); + tokenObject.put("amountLedger", amountLedger); + + if (Functions.multiplePinCheck(senderPeerID, tokenObject, ipfs, receiverPeerId) == 420) { + APIResponse.put("message", "Multiple Owners Found. Kindly re-initiate transaction"); + senderMutex = false; + return APIResponse; + } else { + SenderLogger.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(); + SenderLogger.debug("Token Auth Code: " + tokenAuth); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Token Auth"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "is unable to respond! - Token Auth"); + + return APIResponse; + } + if (tokenAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.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 "419": + String pledgedTokens = input.readLine(); + JSONArray pledgedTokensArray = new JSONArray(pledgedTokens); + SenderLogger.info("These tokens are pledged " + pledgedTokensArray); + SenderLogger.info("Kindly re-initiate transaction"); + APIResponse.put("message", "Pledged Tokens " + pledgedTokensArray + ". Kindly re-initiate transaction"); + File pledgeFile = new File(PAYMENTS_PATH.concat("PledgedTokens.json")); + if (!pledgeFile.exists()) { + pledgeFile.createNewFile(); + writeToFile(PAYMENTS_PATH.concat("PledgedTokens.json"), pledgedTokensArray.toString(), false); + } else { + String pledgedContent = readFile(PAYMENTS_PATH.concat("PledgedTokens.json")); + JSONArray pledgedArray = new JSONArray(pledgedContent); + for (int i = 0; i < pledgedTokensArray.length(); i++) { + pledgedArray.put(pledgedTokensArray.getJSONObject(i)); + } + writeToFile(PAYMENTS_PATH.concat("PledgedTokens.json"), pledgedArray.toString(), false); + } + break; + case "420": + String doubleSpent = input.readLine(); + String owners = input.readLine(); + JSONArray ownersArray = new JSONArray(owners); + SenderLogger.info("Multiple Owners for " + doubleSpent); + SenderLogger.info("Owners " + ownersArray); + SenderLogger.info("Kindly re-initiate transaction"); + APIResponse.put("message", "Multiple Owners for " + doubleSpent + " Owners: " + ownersArray + + ". Kindly re-initiate transaction"); + break; + case "421": + SenderLogger.info("Consensus ID not unique. Kindly re-initiate transaction"); + APIResponse.put("message", "Consensus ID not unique. Kindly re-initiate transaction"); + break; + case "422": + SenderLogger.info("Tokens Not Verified. Kindly re-initiate transaction"); + APIResponse.put("message", "Tokens Not Verified. Kindly re-initiate transaction"); + break; + case "423": + SenderLogger.info("Broken Cheque Chain. Kindly re-initiate transaction"); + APIResponse.put("message", "Broken Cheque Chain. Kindly re-initiate transaction"); + break; + + case "425": + SenderLogger.info("Token wholly spent already. Kindly re-initiate transaction"); + APIResponse.put("message", "Token wholly spent already. Kindly re-initiate transaction"); + break; + + case "426": + SenderLogger.info("Contains Invalid Tokens. Kindly check tokens in your wallet"); + APIResponse.put("message", "Contains Invalid Tokens. Kindly check tokens in your wallet"); + break; + + case "430": + SenderLogger + .info("Token chain verification has failed. Whole token chain/chains could not be verified."); + APIResponse.put("message", "Token Chain/(s) could not be verified."); + break; + + case "431": + SenderLogger + .info("Token chain verification has failed. Part token chain/chains could not be verified."); + APIResponse.put("message", "Token Chain/(s) could not be verified."); + break; + case "432": + SenderLogger.info("Receiver unable to get Quorum(s) public data"); + APIResponse.put("message", "Receiver unable to get Quorum(s) public data"); + break; + + case "433": + SenderLogger.info("Receiver unable to get Sender public data"); + APIResponse.put("message", "Receiver unable to get Sender public data"); + break; + + } + 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"); + return APIResponse; + } + + String pinAuth; + try { + pinAuth = input.readLine(); + SenderLogger.debug("Pin Auth Code: " + pinAuth); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Pin Auth"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "is unable to respond! - Pin Auth"); + + return APIResponse; + } + if (pinAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.info("Receiver is unable to pin 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 tokens!"); + return APIResponse; + } else if (pinAuth != null && (pinAuth.contains("count mistmatch"))) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.info("Receiver is unable to pin tokens - count mismatch!"); + 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 tokens - count mismatch"); + return APIResponse; + } else { + APIResponse.put("tid", tid); + APIResponse.put("status", "Success"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("message", "Tokens transferred successfully!"); + APIResponse.put("receiver", receiverDidIpfsHash); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + output.close(); + input.close(); + senderSocket.close(); + senderMutex = false; + + JSONObject partCPayload = new JSONObject(); + partCPayload.put("quorumWithSignsArray", quorumWithSignsArray); + partCPayload.put("requestedAmount", requestedAmount); + partCPayload.put("port", port); + partCPayload.put("receiverDidIpfsHash", receiverDidIpfsHash); + partCPayload.put("pvt", pvt); + partCPayload.put("type", type); + partCPayload.put("receiverPeerId", receiverPeerId); + partCPayload.put("comment", comment); + partCPayload.put("senderSign", senderSign); + partCPayload.put("signedChains", signedChains); + partCPayload.put("amount", requestedAmount); + partCPayload.put("decimalPart", decimalAmount); + partCPayload.put("senderPayloadSign", senderPayloadSign); + partCPayload.put("authSenderByRecHash", getSignFromShares(pvt, authSenderByRecHash)); +// SenderLogger.debug(partCPayload.toString()); + // resetVariables(); + SendPartC(partCPayload, ipfs); + + return APIResponse; + } + + } + + public static JSONObject SendPartC(JSONObject signPayload, IPFS ipfs) + throws JSONException, IOException, InterruptedException, ParseException, Exception { + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + SenderLogger.debug("Transfer Part C"); +// SenderLogger.debug(signPayload.toString()); + + JSONObject APIResponse = new JSONObject(); + String senderPeerID = getPeerID(DATA_PATH + "DID.json"); + String senderDidIpfsHash = getValues(DATA_PATH + "DataTable.json", "didHash", "peerid", senderPeerID); + + JSONArray quorumWithSignsArray = signPayload.getJSONArray("quorumWithSignsArray"); + double requestedAmount = signPayload.getDouble("requestedAmount"); + int port = signPayload.getInt("port"); + String receiverDidIpfsHash = signPayload.getString("receiverDidIpfsHash"); + String pvt = signPayload.getString("pvt"); + int type = signPayload.getInt("type"); + String receiverPeerId = signPayload.getString("receiverPeerId"); + String comment = signPayload.getString("comment"); + String senderSign = signPayload.getString("senderSign"); + JSONArray signedChains = signPayload.getJSONArray("signedChains"); + double amount = signPayload.getDouble("amount"); + double decimalAmount = signPayload.getDouble("decimalPart"); + + JSONObject senderDetails2Receiver = new JSONObject(); + + // detailsObject.remove("pvtKeyPass"); + if (senderMutex) { + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Sender busy. Try again later"); + SenderLogger.warn("Sender busy"); + resetVariables(); + return APIResponse; + } + + senderMutex = true; + long startTime = System.currentTimeMillis(); + if (Initiator.pledge(quorumWithSignsArray, requestedAmount, port)) { + SenderLogger.debug("Pledging completed"); + JSONObject dataObject = new JSONObject(); + dataObject.put("tid", tid); + dataObject.put("senderPayloadHash", senderPayloadHash); + dataObject.put("senderPayloadSign", signPayload.getString("senderPayloadSign")); + 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); + dataObject.put("sign", signPayload.getString("authSenderByRecHash")); + dataObject.put("hash", authSenderByRecHash); + + InitiatorProcedure.consensusSetUp(dataObject.toString(), ipfs, SEND_PORT + 100, alphaSize, ""); + + if (InitiatorConsensus.quorumSignature.length() < (minQuorum(alphaSize))) { + SenderLogger.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"); + resetVariables(); + return APIResponse; + + } + + SenderLogger.debug("Consensus Reached"); + + SenderLogger.debug("Sender IPFS forwarding to receiver: " + receiverDidIpfsHash + " PeerID: " + + receiverPeerId + " - Part C"); + forward(receiverPeerId.concat("step"), port, receiverPeerId); + SenderLogger.debug("Forwarded to " + receiverPeerId + " on " + port); + senderSocket = new Socket("127.0.0.1", port); + + input = new BufferedReader(new InputStreamReader(senderSocket.getInputStream())); + output = new PrintStream(senderSocket.getOutputStream()); + + senderDetails2Receiver.put("tid", tid); + senderDetails2Receiver.put("pvtShareBits", signPayload.getString("authSenderByRecHash")); + senderDetails2Receiver.put("comment", comment); + senderDetails2Receiver.put("status", "Consensus Reached"); + senderDetails2Receiver.put("quorumsign", InitiatorConsensus.quorumSignature.toString()); + senderDetails2Receiver.put("pledgeDetails", Initiator.pledgedTokensArray); + senderDetails2Receiver.put("senderDidIpfsHash", senderDidIpfsHash); + senderDetails2Receiver.put("intPart", intPart); + senderDetails2Receiver.put("wholeTokenChains", wholeTokenChainHash); + senderDetails2Receiver.put("wholeTokens", wholeTokens); + senderDetails2Receiver.put("partTokens", partTokens); + senderDetails2Receiver.put("partTokenChainsHash", partTokenChainHash); + senderDetails2Receiver.put("distributedObject", Initiator.distributedObject); + senderDetails2Receiver.put("part-tokenChains", partTokenChainArrays); + senderDetails2Receiver.put("amountLedger", amountLedger); + senderDetails2Receiver.put("amount", amount); + senderDetails2Receiver.put("decimalPart", decimalAmount); + + output.println("PartC"); + output.println(senderDetails2Receiver); + + String signatureAuth; + try { + signatureAuth = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Signature Auth"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Receiver " + receiverDidIpfsHash + "is unable to respond! - Signature Auth"); + resetVariables(); + + return APIResponse; + } + SenderLogger.info("signatureAuth : " + signatureAuth); + long endTime = System.currentTimeMillis(); + long totalTime = endTime - startTime; + if (signatureAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.info("Receiver is unable to authenticate 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 Sender!"); + resetVariables(); + return APIResponse; + } else if (signatureAuth != null && (!signatureAuth.equals("200"))) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.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"); + resetVariables(); + return APIResponse; + + } + + // Sender requests for new block that is going to be added to the Token chains. + // (For Token chain auth) + output.println("Request for new blocks being added to the Token Chains"); + + String newBlocksForTokenChains; + try { + newBlocksForTokenChains = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + + " could'nt send token chain blocks for hashing and signing"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Receiver " + receiverDidIpfsHash + "couldn't send token chain blocks for hashing and signing"); + resetVariables(); + return APIResponse; + } + + // TokenSenderLogger.debug("newBlocksForTokenChains is " + + // newBlocksForTokenChains); + // TokenSenderLogger.debug(""); + + // TokenSenderLogger.debug("lastObJsonArray is " + lastObJsonArray.toString()); + + JSONArray newTokenChainBlocks = new JSONArray(newBlocksForTokenChains); + JSONArray hashAndSigns = new JSONArray(); + + for (int i = 0; i < intPart; i++) { + JSONObject lastObject = lastObJsonArray.getJSONObject(i); + JSONObject receiverLastObject = newTokenChainBlocks.getJSONObject(i).getJSONObject("lastObject"); + + Map senderChainMap = lastObject.toMap(); + Map receiverChainMap = receiverLastObject.toMap(); + senderChainMap.remove("pledgeToken"); + receiverChainMap.remove("pledgeToken"); + senderChainMap.remove("distributedObject"); + receiverChainMap.remove("distributedObject"); + + // TokenSenderLogger.debug("--------"); + // TokenSenderLogger.debug("senderChainMap " + + // senderChainMap.keySet().toString()); + // TokenSenderLogger.debug("senderChainMap " + + // senderChainMap.values().toString()); + + // TokenSenderLogger.debug("--------"); + // TokenSenderLogger.debug("receiverChainMap " + + // receiverChainMap.keySet().toString()); + // TokenSenderLogger.debug("receiverChainMap " + + // receiverChainMap.values().toString()); + + // TokenSenderLogger.debug("--------"); + + // TokenSenderLogger.debug(senderChainMap.equals(receiverChainMap) + " is the + // chainmap status"); + + // TokenSenderLogger.debug("signedChains is " + signedChains.toString()); + if (senderChainMap.equals(receiverChainMap)) { + + // String PvtKeySign = + // pvtKeySign(signedChains.getJSONObject(i).getString("chainSign"), pvtKey, + // privateKeyAlgorithm(1)); + + JSONObject obj = new JSONObject(); + obj.put("hash", signedChains.getJSONObject(i).getString("hash")); + obj.put("pvtShareBits", signedChains.getJSONObject(i).getString("chainSign")); + // obj.put("pvtKeySign", PvtKeySign); + + hashAndSigns.put(obj); + } else { + output.println("Token chains Not Matching"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.info("Token chains Not Matching"); + 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", "Token chains Not Matching"); + resetVariables(); + return APIResponse; + } + } + + output.println(hashAndSigns.toString()); + // Sender requests for new block that is going to be added to the part Token + // chains. +// output.println("Request for Part Token Chains to be hashed"); + +// String req_newPartTokenChains; +// try { +// req_newPartTokenChains = input.readLine(); +// TokenSenderLogger.debug("Hashing and Signing Part Token Chains."); +// } catch (SocketException e) { +// TokenSenderLogger.warn("Receiver " + receiverDidIpfsHash + " could'nt send part token chain blocks for hashing and signing"); +// 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", "null"); +// APIResponse.put("status", "Failed"); +// APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "could'nt send part token chain blocks for hashing and signing"); + // +// return APIResponse; +// } + // +// JSONObject newPartTokenChains= new JSONObject(req_newPartTokenChains); + // + +// output.println(hashesAndSigns_partTokenChains.toString()); //Sending the hashes and signs for the part token chains sent by receiver. + + SenderLogger.debug("Unpinned Tokens"); + output.println("Unpinned"); + +// String confirmation; +// try { +// confirmation = input.readLine(); +// } catch (SocketException e) { +// SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Pinning Auth"); +// 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", "null"); +// APIResponse.put("status", "Failed"); +// APIResponse.put("message", "Receiver " + receiverDidIpfsHash + "is unable to respond! - Pinning Auth"); +// resetVariables(); + // +// return APIResponse; +// } +// if (confirmation == null) { +// executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); +// SenderLogger.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!"); +// resetVariables(); +// return APIResponse; + // +// } else if (confirmation != null && (!confirmation.equals("Successfully Pinned"))) { +// SenderLogger.warn("Multiple Owners for the token"); +// executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); +// SenderLogger.info("Tokens with multiple pins"); +// 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", "Tokens with multiple pins"); +// resetVariables(); +// return APIResponse; + // +// } + output.println(InitiatorProcedure.essential); + + String respAuth; + try { + respAuth = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + " is unable to Respond! - Share Confirmation"); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", + "Receiver " + receiverDidIpfsHash + "is unable to respond! - Share Confirmation"); + resetVariables(); + + return APIResponse; + } + if (respAuth == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + receiverPeerId); + SenderLogger.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!"); + resetVariables(); + + return APIResponse; + + } else if (respAuth != null && (!respAuth.equals("Send Response"))) { + 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", "Receiver process not over"); + SenderLogger.info("Incomplete Transaction"); + + resetVariables(); + return APIResponse; + } + + SenderLogger.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()) + * signedQuorumList.put(keys.next()); + */ + + JSONArray QuorumSignatures = new JSONArray(InitiatorConsensus.quorumSignature.toString()); + JSONArray signedQuorumList = new JSONArray(); + JSONObject temp = new JSONObject(); + + for (int i = 0; i < QuorumSignatures.length(); i++) { + + temp = QuorumSignatures.getJSONObject(i); + signedQuorumList.put(temp.getString("quorum_did")); + } + + APIResponse.put("tid", tid); + APIResponse.put("status", "Success"); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("message", "Tokens transferred successfully!"); + APIResponse.put("quorumlist", signedQuorumList); + APIResponse.put("receiver", receiverDidIpfsHash); + APIResponse.put("totaltime", totalTime); + + JSONObject transactionRecord = new JSONObject(); + transactionRecord.put("role", "Sender"); + transactionRecord.put("tokens", allTokens); + transactionRecord.put("txn", tid); + transactionRecord.put("quorumList", signedQuorumList); + transactionRecord.put("senderDID", senderDidIpfsHash); + transactionRecord.put("receiverDID", receiverDidIpfsHash); + transactionRecord.put("Date", getCurrentUtcTime()); + transactionRecord.put("totalTime", totalTime); + transactionRecord.put("comment", comment); + transactionRecord.put("essentialShare", InitiatorProcedure.essential); + 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++) { + deleteFile(TOKENS_PATH.concat(wholeTokens.getString(i))); + Functions.updateJSON("remove", PAYMENTS_PATH.concat("BNK00.json"), wholeTokens.getString(i)); + } + if (decimalAmount != 0.0) { + + if (newPart) { + SenderLogger.debug("Updating files for new parts"); + JSONObject newPartTokenObject = new JSONObject(); + newPartTokenObject.put("tokenHash", partTokens.getString(0)); + JSONArray newPartArray = new JSONArray(); + newPartArray.put(newPartTokenObject); + writeToFile(PAYMENTS_PATH.concat("PartsToken.json"), newPartArray.toString(), false); + + String bankNew = readFile(PAYMENTS_PATH.concat("BNK00.json")); + JSONArray bankNewArray = new JSONArray(bankNew); + bankNewArray.remove(0); + writeToFile(PAYMENTS_PATH.concat("BNK00.json"), bankNewArray.toString(), false); + + String newTokenChain = readFile(TOKENCHAIN_PATH + partTokens.getString(0) + ".json"); + JSONArray chainArray = new JSONArray(newTokenChain); + + JSONObject newLastObject = new JSONObject(); + /* + * if (chainArray.length() == 0) { newLastObject.put("previousHash", ""); + * + * } 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")); } + */ + + Double decimalPrtAmount = formatAmount(decimalAmount); + + newLastObject.put("senderSign", senderSign); + newLastObject.put("sender", senderDidIpfsHash); + newLastObject.put("receiver", receiverDidIpfsHash); + newLastObject.put("comment", comment); + newLastObject.put("tid", tid); + // newLastObject.put("nextHash", ""); + newLastObject.put("role", "Sender"); + newLastObject.put("amount", decimalPrtAmount); + chainArray.put(newLastObject); + + output.println("New part token chain to be hashed"); + output.println(chainArray.toString()); + + // TokenSenderLogger.debug("!@#$% 1: " + chainArray); + + String finalPartTokenChain_string; + try { + finalPartTokenChain_string = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + + " could'nt send hahsed and signed token chain blocks."); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver " + receiverDidIpfsHash + + " could'nt send hahsed and signed token chain blocks."); + resetVariables(); + + return APIResponse; + } + // TokenSenderLogger.debug("!@#$% 2: " + finalPartTokenChain_string); + + JSONArray newPartTokenChain = new JSONArray(finalPartTokenChain_string); + writeToFile(TOKENCHAIN_PATH + partTokens.getString(0) + ".json", newPartTokenChain.toString(), + false); + + File tokenFile = new File(TOKENS_PATH.concat(partTokens.getString(0))); + tokenFile.renameTo(new File(PART_TOKEN_PATH.concat(partTokens.getString(0)))); + 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(); + JSONArray shiftedTokensArray = new JSONArray(); + shiftedTokensArray.put(partTokens.getString(0)); + writeToFile(PAYMENTS_PATH.concat("ShiftedTokens.json"), shiftedTokensArray.toString(), false); + } else { + String shiftedContent = readFile(PAYMENTS_PATH.concat("ShiftedTokens.json")); + JSONArray shiftedArray = new JSONArray(shiftedContent); + shiftedArray.put(partTokens.getString(0)); + writeToFile(PAYMENTS_PATH.concat("ShiftedTokens.json"), shiftedArray.toString(), false); + } + } else { + + JSONObject partTokenChainsToBeSentForHashing = new JSONObject(); + +// SenderLogger.debug("Updating files for old parts"); + for (int i = 0; i < partTokens.length(); i++) { + String newTokenChain = readFile( + TOKENCHAIN_PATH.concat("PARTS/") + partTokens.getString(i) + ".json"); + JSONArray chainArray = new JSONArray(newTokenChain); + + JSONObject newLastObject = new JSONObject(); + + /* + * if (chainArray.length() == 0) { newLastObject.put("previousHash", ""); + * + * } 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")); } + */ + + Double amountLedgerAmount = formatAmount(amountLedger.getDouble(partTokens.getString(i))); + + newLastObject.put("senderSign", senderSign); + newLastObject.put("sender", senderDidIpfsHash); + newLastObject.put("receiver", receiverDidIpfsHash); + newLastObject.put("comment", comment); + newLastObject.put("tid", tid); + // newLastObject.put("nextHash", ""); + newLastObject.put("role", "Sender"); + newLastObject.put("amount", amountLedgerAmount); + chainArray.put(newLastObject); + + partTokenChainsToBeSentForHashing.put(partTokens.getString(i), chainArray); + +// SenderLogger.debug("Checking Parts Token Balance ..."); + Double availableParts = partTokenBalance(partTokens.getString(i)); + if (availableParts >= 1.000 || availableParts <= 0.000) { +// SenderLogger.debug("Wholly Spent, Removing token from parts"); + String partFileContent2 = readFile(PAYMENTS_PATH.concat("PartsToken.json")); + JSONArray partContentArray2 = new JSONArray(partFileContent2); + for (int j = 0; j < partContentArray2.length(); j++) { + if (partContentArray2.getJSONObject(j).getString("tokenHash") + .equals(partTokens.getString(i))) + partContentArray2.remove(j); + writeToFile(PAYMENTS_PATH.concat("PartsToken.json"), partContentArray2.toString(), + false); + } + deleteFile(PART_TOKEN_PATH.concat(partTokens.getString(i))); + } + } + output.println("Old part token chains to be hashed"); + output.println(partTokenChainsToBeSentForHashing.toString()); + // TokenSenderLogger.debug("!@#$% 3: " + partTokenChainsToBeSentForHashing); + + String hashedPartTokenChains_string; + try { + hashedPartTokenChains_string = input.readLine(); + } catch (SocketException e) { + SenderLogger.warn("Receiver " + receiverDidIpfsHash + + " could'nt send hahsed and signed token chain blocks."); + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Receiver " + receiverDidIpfsHash + + " could'nt send hahsed and signed token chain blocks."); + resetVariables(); + + return APIResponse; + } + + // TokenSenderLogger.debug("!@#$% 4: " + hashedPartTokenChains_string); + + JSONObject finalPartTokenChains = new JSONObject(hashedPartTokenChains_string); + for (int i = 0; i < partTokens.length(); i++) { + + JSONArray chainArray = finalPartTokenChains.getJSONArray(partTokens.getString(i)); + writeToFile(TOKENCHAIN_PATH.concat("PARTS/").concat(partTokens.getString(i)).concat(".json"), + chainArray.toString(), false); + } + + 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)) + bnkArray.remove(i); + } + writeToFile(PAYMENTS_PATH.concat("BNK00.json"), bnkArray.toString(), false); + + JSONArray pArray = new JSONArray(); + JSONObject pObject = new JSONObject(); + pObject.put("tokenHash", token); + pArray.put(pObject); + writeToFile(PAYMENTS_PATH.concat("PartsToken.json"), pArray.toString(), false); + + } + } + } + SenderLogger.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<>(); + for (int i = 0; i < allTokens.length(); i++) + tokenList.add(allTokens.getString(i)); + String url = EXPLORER_IP + "/CreateOrUpdateRubixTransaction"; + URL obj = new URL(url); + HttpsURLConnection con = (HttpsURLConnection) obj.openConnection(); + + // Setting basic post request + con.setRequestMethod("POST"); + con.setRequestProperty("Accept-Language", "en-US,en;q=0.5"); + con.setRequestProperty("Accept", "application/json"); + con.setRequestProperty("Content-Type", "application/json"); + con.setRequestProperty("Authorization", "null"); + + // Serialization + JSONObject dataToSend = new JSONObject(); + dataToSend.put("transaction_id", tid); + dataToSend.put("sender_did", senderDidIpfsHash); + dataToSend.put("receiver_did", receiverDidIpfsHash); + dataToSend.put("token_id", tokenList); + dataToSend.put("token_time", (int) totalTime); + dataToSend.put("amount", requestedAmount); + String populate = dataToSend.toString(); + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("inputString", populate); + String postJsonData = jsonObject.toString(); + + // Send post request + con.setDoOutput(true); + DataOutputStream wr = new DataOutputStream(con.getOutputStream()); + wr.writeBytes(postJsonData); + wr.flush(); + wr.close(); + + int responseCode = con.getResponseCode(); + SenderLogger.debug("Sending 'POST' request to URL : " + url); + SenderLogger.debug("Post Data : " + postJsonData); + SenderLogger.debug("Response Code : " + responseCode); + + BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); + String output; + StringBuffer response = new StringBuffer(); + + while ((output = in.readLine()) != null) { + response.append(output); + } + in.close(); + + SenderLogger.debug(response.toString()); + } + + senderMutex = false; + resetVariables(); + return APIResponse; + } else { + + 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", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Pledge failed"); + resetVariables(); + return APIResponse; + + } + + } +} \ No newline at end of file diff --git a/src/com/rubix/Ping/VerifyStakedToken.java b/src/com/rubix/Ping/VerifyStakedToken.java index bd599f54..8939e26c 100644 --- a/src/com/rubix/Ping/VerifyStakedToken.java +++ b/src/com/rubix/Ping/VerifyStakedToken.java @@ -18,6 +18,7 @@ import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -26,8 +27,9 @@ 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 JSONArray tokenChain; - public static boolean Contact(String pid, int port, String tokenHash, String tokenContent) + public static boolean Contact(String pid, int port, String tokenHash, String tokenContent, String pingMessage) throws IOException, JSONException { repo(ipfs); PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); @@ -42,78 +44,123 @@ public static boolean Contact(String pid, int port, String tokenHash, String tok 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; - } + output.println(pingMessage); + + if(pingMessage.equals("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); - } + 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); + 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; + } + else{ + tokenChain = new JSONArray(); + output.println(tokenHash); + String tokenChainResponse; + try { + tokenChainResponse = input.readLine(); + } catch (SocketException e) { + PingSenderLogger.warn("Node " + pid + " is unable to Respond! - Token Chain Ping"); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + pid); + output.close(); + input.close(); + senderSocket.close(); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Node " + pid + "is unable to respond! - Token Chain Ping"); + + return false; } - 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) { + + if (tokenChainResponse == null) { + executeIPFSCommands(" ipfs p2p close -t /p2p/" + pid); + PingSenderLogger.info("TokenChain not received"); + output.close(); + input.close(); + senderSocket.close(); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "TokenChain not received"); + return false; + + } else { + tokenChain = new JSONArray(tokenChainResponse); + PingSenderLogger.info("TokenChain received from " + pid); + PingSenderLogger.info("TokenChain: " + tokenChainResponse); + executeIPFSCommands(" ipfs p2p close -t /p2p/" + pid); + output.close(); + input.close(); + senderSocket.close(); + APIResponse.put("status", "Success"); + APIResponse.put("message", "Tokenchain Received"); 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 2627e5fd..6f16a737 100644 --- a/src/com/rubix/Resources/APIHandler.java +++ b/src/com/rubix/Resources/APIHandler.java @@ -15,6 +15,8 @@ import static com.rubix.Resources.IPFSNetwork.add; import static com.rubix.Resources.IPFSNetwork.executeIPFSCommands; import static com.rubix.Resources.IPFSNetwork.pin; +import com.rubix.ConvinientTransfer.*; + import java.io.BufferedReader; import java.io.File; @@ -50,6 +52,56 @@ public class APIHandler { private static final Logger APILogger = Logger.getLogger(APIHandler.class); public static IPFS ipfs = new IPFS("/ip4/127.0.0.1/tcp/" + IPFS_PORT); private static final Logger eventLogger = Logger.getLogger("eventLogger"); + + /** + * (2-Step) Initiates a transfer between two nodes + * + * @param data Data specific to token transfer + * @return Message from the sender with transaction details + * @throws JSONException handles JSON Exceptions + * @throws NoSuchAlgorithmException handles Invalid Algorithms Exceptions + * @throws IOException handles IO Exceptions + */ + + public static JSONObject twoStepSend(String data) throws Exception { + Functions.pathSet(); + PropertyConfigurator.configure(LOGGER_PATH + "log4jWallet.properties"); + + String senderPeerID = getPeerID(DATA_PATH + "DID.json"); + String senDID = getValues(DATA_PATH + "DID.json", "didHash", "peerid", senderPeerID); + + JSONObject dataObject = new JSONObject(data); + String recDID = dataObject.getString("receiverDidIpfsHash"); + + 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 (dataTableObject.getString("didHash").equals(recDID)) { + isObjectValid = true; + } + } + if (!isObjectValid) + networkInfo(); + + JSONObject sendMessage = new JSONObject(); + if (recDID.length() != 46) { + sendMessage.put("did", senDID); + sendMessage.put("tid", "null"); + sendMessage.put("status", "Failed"); + sendMessage.put("message", "Invalid Receiver Did Entered"); + return sendMessage; + } + //***-----------------**** + //PVT Share here + //***-----------------**** + dataObject.put("pvt", DATA_PATH + senDID + "/PrivateShare.png"); + sendMessage = com.rubix.ConvinientTransfers.Sender.SendPartA(dataObject.toString(), ipfs, SEND_PORT); + + // APILogger.info(sendMessage); + return sendMessage; + } /** * Initiates a transfer between two nodes diff --git a/src/com/rubix/Resources/Functions.java b/src/com/rubix/Resources/Functions.java index d9857bdb..ec2d29fb 100644 --- a/src/com/rubix/Resources/Functions.java +++ b/src/com/rubix/Resources/Functions.java @@ -2638,7 +2638,7 @@ else if(share3.exists() && share4.exists()){ return result; } - public static JSONObject verifySpecificCommit(String blockHash) { + public static JSONObject verifySpecificCommit(String blockHash) throws JSONException { JSONObject APIResponse = new JSONObject(); String transcationID = null; String senderDidIpfsHash = null; diff --git a/src/com/rubix/TokenTransfer/TokenReceiver.java b/src/com/rubix/TokenTransfer/TokenReceiver.java index 684c0ce6..fda90b62 100644 --- a/src/com/rubix/TokenTransfer/TokenReceiver.java +++ b/src/com/rubix/TokenTransfer/TokenReceiver.java @@ -30,6 +30,9 @@ import com.rubix.Resources.Functions; import com.rubix.Resources.IPFSNetwork; import com.rubix.TokenTransfer.TransferPledge.Unpledge; + +import Fork.ForkResolution; + import com.rubix.Constants.MiningConstants.*; import static com.rubix.Resources.APIHandler.getPubKeyIpfsHash_DIDserver; @@ -199,6 +202,8 @@ public static String receive() { JSONObject partTokenChains = TokenDetails.getJSONObject("part-tokenChains"); JSONObject partTokenChainsForVerification = TokenDetails.getJSONObject("part-tokenChains-PrevState"); JSONArray partTokenChainsHash = TokenDetails.getJSONArray("hashSender"); + JSONObject distributedObject = TokenDetails.getJSONObject("distributedObject"); + if (TokenDetails.optJSONArray("proof") != null) { JSONArray proofArray = TokenDetails.getJSONArray("proof"); @@ -276,26 +281,26 @@ public static String receive() { TokenReceiverLogger.debug("Ipfs dht find did not execute"); } } - if (multiplePin) { - 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(); - } +// if (multiplePin) { +// 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"); @@ -343,6 +348,65 @@ public static String receive() { tokenMaxLimitMap.put(tokenNumberHash, tokenLimitForLevel); tokenDetailMap.put(tokenNumberHash, -1); } + + if (intPart > 0) { + + boolean forkResolution = true; + TokenReceiverLogger.debug("Fork Checking version 3: "); + // TokenReceiverLogger.debug("Whole Token Chains: " + wholeTokenChainContent.get(0)); + // TokenReceiverLogger.debug("Whole Token Chains: " + new JSONArray(wholeTokenChainContent.get(0))); + JSONArray forkedTokens = new JSONArray(); + for (int i = 0; i < wholeTokens.length(); ++i) { + TokenReceiverLogger.debug("Fork Checking for token: " + wholeTokens.getString(i)); + + JSONArray tokenChain = new JSONArray(wholeTokenChainContent.get(i)); + JSONObject forkObject = new JSONObject(); + forkObject.put("token", wholeTokens.getString(i)); + forkObject.put("tokenChain", tokenChain); + forkObject.put("previousSendersArray", previousSendersArray); + forkObject.put("currentSender", senderPeerID); + forkObject.put("currentReceiver", receiverPeerID); + + if (tokenChain.getJSONObject(tokenChain.length() - 1).has("pledgeToken")) { + TokenReceiverLogger + .debug("Token " + wholeTokens.getString(i) + " is a new token (SHAG structure)"); + if (!tokenChain.getJSONObject(tokenChain.length() - 1).getString("pledgeToken").equals("")) { + TokenReceiverLogger.debug("Token " + wholeTokens.getString(i) + " is a pledged token"); + forkResolution = ForkResolution.verifyUnpledgedToken(wholeTokens.getString(i), + tokenChain.getJSONObject(tokenChain.length() - 1).getJSONArray("tokensPledgedFor") + .get(0).toString(), senderPeerID, receiverPeerID); + + } else { + TokenReceiverLogger.debug("Token " + wholeTokens.getString(i) + + " is a new token (SHAG structure) and not pledged"); + forkResolution = ForkResolution.check(forkObject); + } + } else { + TokenReceiverLogger.debug("Token " + wholeTokens.getString(i) + " is an Eismeer Token"); + forkResolution = ForkResolution.check(forkObject); + } + if (!forkResolution) { + TokenReceiverLogger.debug("Fork found and not resolved for token: " + wholeTokens.getString(i)); + TokenReceiverLogger.debug("Message: " + ForkResolution.resolutionMessage); + forkedTokens.put(wholeTokens.getString(i)); + } + } + if (!forkResolution) { + TokenReceiverLogger.debug("Fork not resolved for " + forkedTokens); + output.println("418"); + output.println(forkedTokens.toString()); + APIResponse.put("did", senderDidIpfsHash); + APIResponse.put("tid", "null"); + APIResponse.put("status", "Failed"); + APIResponse.put("message", "Fork not resolved"); + IPFSNetwork.executeIPFSCommands(" ipfs p2p close -t /p2p/" + senderPeerID); + output.close(); + input.close(); + sk.close(); + ss.close(); + return APIResponse.toString(); + } + } //QmWcmK38g9XcrCwhoEq3rQjNseJW2HyscoG66DWF62X6bK.proof @@ -1309,7 +1373,7 @@ public static String receive() { 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"))) { + mineIDContentJSON.getString("tokenContent"), "Get-TokenChain-Height")) { minedTokenStatus = false; } } @@ -1698,6 +1762,8 @@ public static String receive() { lastObject.put("pledgeToken", ""); lastObject.put("tokensPledgedFor", allTokens); lastObject.put("tokensPledgedWith", pledgedDetails); + lastObject.put("distributedObject", distributedObject); + if (!BlockHash.isEmpty()) { lastObject.put("blockHash", BlockHash); @@ -1824,6 +1890,10 @@ public static String receive() { newPartObject.put("receiver", receiverDidIpfsHash); newPartObject.put("comment", comment); newPartObject.put("tid", tid); + newPartObject.put("pledgeToken", ""); + newPartObject.put("tokensPledgedFor", allTokens); + newPartObject.put("tokensPledgedWith", pledgedDetails); + newPartObject.put("distributedObject", distributedObject); // newPartObject.put("nextHash", ""); // newPartObject.put("owner", ownerIdentityHash); /* diff --git a/src/com/rubix/TokenTransfer/TokenSender.java b/src/com/rubix/TokenTransfer/TokenSender.java index f826d106..ff8bf967 100644 --- a/src/com/rubix/TokenTransfer/TokenSender.java +++ b/src/com/rubix/TokenTransfer/TokenSender.java @@ -584,6 +584,7 @@ public static JSONObject SendPartA(String data, IPFS ipfs, int port) throws Exce lastObject.put("pledgeToken", ""); lastObject.put("tokensPledgedFor", allTokens); lastObject.put("tokensPledgedWith", Initiator.pledgedTokensArray); + lastObject.put("distributedObject", Initiator.distributedObject); String tokenChainFileContent = readFile(TOKENCHAIN_PATH + wholeTokens.get(i) + ".json"); JSONArray tokenChain = new JSONArray(tokenChainFileContent); @@ -932,6 +933,7 @@ public static JSONObject SendPartB(JSONObject signPayload, IPFS ipfs, int port) tokenDetails.put("part-tokenChains-PrevState", partTokenChainsPrevState); tokenDetails.put("sender", senderDidIpfsHash); tokenDetails.put("proof", proofOfWork); + tokenDetails.put("distributedObject", Initiator.distributedObject); String doubleSpendString = tokenDetails.toString(); //TokenSenderLogger.debug("tokenDetails is "+tokenDetails.toString()); @@ -1221,6 +1223,9 @@ public static JSONObject SendPartB(JSONObject signPayload, IPFS ipfs, int port) Map receiverChainMap = receiverLastObject.toMap(); senderChainMap.remove("pledgeToken"); receiverChainMap.remove("pledgeToken"); + senderChainMap.remove("distributedObject"); + receiverChainMap.remove("distributedObject"); + //TokenSenderLogger.debug("--------"); //TokenSenderLogger.debug("senderChainMap " + senderChainMap.keySet().toString()); diff --git a/src/com/rubix/TokenTransfer/TransferPledge/Initiator.java b/src/com/rubix/TokenTransfer/TransferPledge/Initiator.java index 6cbf06a6..67594956 100644 --- a/src/com/rubix/TokenTransfer/TransferPledge/Initiator.java +++ b/src/com/rubix/TokenTransfer/TransferPledge/Initiator.java @@ -4,7 +4,6 @@ import io.ipfs.api.IPFS; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; -import org.bouncycastle.LICENSE; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -35,6 +34,7 @@ public class Initiator { public static JSONObject abortReason = new JSONObject(); public static JSONArray tokenList = new JSONArray(); + public static JSONObject distributedObject; public static JSONArray nodesToPledgeTokens = new JSONArray(); public static JSONObject quorumDetails = new JSONObject(); public static JSONArray quorumWithHashesArray = new JSONArray(); @@ -45,6 +45,7 @@ public class Initiator { public static String keyPass; public static JSONObject quorumHashObject = new JSONObject(); public static boolean pledged = false; + public static JSONArray alphaList = new JSONArray(); public static JSONArray pledgedTokensArray = new JSONArray(); @@ -53,7 +54,9 @@ public class Initiator { public static void resetVariables() { + alphaList = new JSONArray(); pledgedNodes = new JSONArray(); + distributedObject = new JSONObject(); abortReason = new JSONObject(); tokenList = new JSONArray(); nodesToPledgeTokens = new JSONArray(); @@ -81,8 +84,8 @@ public static boolean pledgeSetUp(String data, IPFS ipfs, int PORT) throws JSONE // PledgeInitiatorLogger.debug("pledgeSetUp dataObject is // "+dataObject.toString()); - JSONArray alphaList = dataObject.getJSONArray("alphaList"); - pvt = dataObject.getString("pvt"); + alphaList = dataObject.getJSONArray("alphaList"); + pvt = dataObject.getString("pvt"); tid = dataObject.getString("tid"); String keyPass = dataObject.getString("pvtKeyPass"); sender = dataObject.getString("sender"); @@ -179,6 +182,7 @@ public static boolean pledgeSetUp(String data, IPFS ipfs, int PORT) throws JSONE pledgeNewObject.put("pledgeToken", tokenObject.getString("tokenHash")); pledgeNewObject.put("tokensPledgedFor", tokenList); pledgeNewObject.put("tokensPledgedWith", tokenObject.getString("tokenHash")); + pledgeNewObject.put("distributedObject", new JSONObject()); // pledgedTokensArray.put(tokenObject.getString("tokenHash")); @@ -213,6 +217,7 @@ public static boolean pledgeSetUp(String data, IPFS ipfs, int PORT) throws JSONE pledgeNewObject.put("pledgeToken", tokenObject.getString("tokenHash")); pledgeNewObject.put("tokensPledgedFor", tokenList); pledgeNewObject.put("tokensPledgedWith", tokenObject.getString("tokenHash")); + pledgeNewObject.put("distributedObject", new JSONObject()); // pledgedTokensArray.put(tokenObject.getString("tokenHash")); @@ -352,6 +357,7 @@ public static boolean pledge(JSONArray pledgeDetails, double amount, int PORT) pledgeObject.put("pledgeToken", tokenHash); pledgeObject.put("tokensPledgedFor", tokenList); pledgeObject.put("tokensPledgedWith", tokenObject.getString("tokenHash")); + pledgeObject.put("distributedObject", new JSONObject()); tokenChain.put(pledgeObject); pledgedTokensArray.put(tokenObject.getString("tokenHash")); @@ -478,12 +484,56 @@ public static boolean pledge(JSONArray pledgeDetails, double amount, int PORT) } } + closeAllConnections(alphaList); + distributePledgeTokens(tokenList, pledgedTokensArray); if (tokensPledged > 0) abort = true; PledgeInitiatorLogger.debug("Quorum Verification with Tokens or Credits with Abort Status:" + Initiator.abort); return abort; } + + public static void closeAllConnections(JSONArray nodes) throws JSONException{ + for(int i = 0; i < nodes.length(); i++){ + IPFSNetwork.executeIPFSCommands("ipfs p2p close -t /p2p/" + nodes.getString(i)); + } + } + + public static boolean distributePledgeTokens(JSONArray transferTokens, JSONArray pledgedTokens) throws JSONException{ + distributedObject = new JSONObject(); + + PledgeInitiatorLogger.debug("<1> Transfer tokens: " + transferTokens); + PledgeInitiatorLogger.debug("<1> Pledge tokens: " + pledgedTokens); + + if(transferTokens.length() > pledgedTokens.length()) { + PledgeInitiatorLogger.debug("Only Whole Tokens"); + String partPledgedTokenString = pledgedTokens.getString(pledgedTokens.length()-1); + pledgedTokens.remove(pledgedTokens.length()-1); + + PledgeInitiatorLogger.debug("<2> Transfer tokens: " + transferTokens); + PledgeInitiatorLogger.debug("<2> Pledge tokens: " + pledgedTokens); + for(int i = 0; i < transferTokens.length(); i++) { + distributedObject.put(transferTokens.getString(i), pledgedTokens.getString(i)); + transferTokens.remove(i); + } + + PledgeInitiatorLogger.debug("<3> Transfer tokens: " + transferTokens); + PledgeInitiatorLogger.debug("<3> Pledge tokens: " + pledgedTokens); + + for (int i = 0; i < transferTokens.length(); i++) + distributedObject.put(transferTokens.getString(i), partPledgedTokenString); + + }else { + PledgeInitiatorLogger.debug("Parts Tokens Included"); + for(int i = 0; i < transferTokens.length(); i++) { + distributedObject.put(transferTokens.getString(i), pledgedTokens.getString(i)); + } + PledgeInitiatorLogger.debug("<4> Transfer tokens: " + transferTokens); + PledgeInitiatorLogger.debug("<4> Pledge tokens: " + pledgedTokens); + } + + return true; + } public static String fetchSign(JSONArray pledgeArray, String hash) throws JSONException {