diff --git a/README.md b/README.md index 24cb33c..88d7e04 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,17 @@ If you have any ideas please submit a request (I am totally not a Java guy so... #### Multisig - [x] composeAddress -- [x] updateLeafToRoot (needs testing) +- [x] updateLeafToRoot - [x] getDigest #### Model.Transfer -- [x] prepare (needs testing) -- [x] compose (needs testing) +- [x] prepare +- [x] compose - [x] close (needs testing) -- [ ] applyTransfers -- [ ] appliedSignatures -- [ ] getDiff -- [ ] sign +- [x] applyTransfers +- [x] appliedSignatures +- [ ] getDiff (not used at the moment) +- [x] sign @@ -28,6 +28,7 @@ If you have any ideas please submit a request (I am totally not a Java guy so... 1. Clone repo 2. Update maven ressources 3. That's it. +4. You can run a test transaction by running the main func in the Main Class. diff --git a/iotaflashlibjswrapper.iml b/iotaflashlibjswrapper.iml index b793751..94d5fa5 100644 --- a/iotaflashlibjswrapper.iml +++ b/iotaflashlibjswrapper.iml @@ -13,5 +13,6 @@ + \ No newline at end of file diff --git a/pom.xml b/pom.xml index b9968dc..d240599 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,13 @@ iota~lib~java v0.9.10 + + + com.google.code.gson + gson + 2.8.2 + compile + diff --git a/res/iota.flash.js b/res/iota.flash.js index 0e72137..b155739 100644 --- a/res/iota.flash.js +++ b/res/iota.flash.js @@ -9472,7 +9472,7 @@ var is_null = function(arr) { } var trits_to_words = function(trits) { - if (trits.length != 243) { + if (trits.length != 243) { throw "Invalid trits length"; } diff --git a/src/main/java/Helpers.java b/src/main/java/Helpers.java index 45fd8fa..40f3960 100644 --- a/src/main/java/Helpers.java +++ b/src/main/java/Helpers.java @@ -1,6 +1,8 @@ import Model.*; import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; public class Helpers { public static ArrayList createTransaction(UserObject user, ArrayList transfers, boolean shouldClose) { @@ -11,11 +13,10 @@ public class Helpers { System.out.println("No more addresses in channel."); } - ArrayList newTransfers; + ArrayList newTransfers; if (shouldClose) { - newTransfers = new ArrayList<>(); - // newTransfers = IotaFlashBridge.close(user.getFlash().getSettlementAddresses(), user.getFlash().deposits); + newTransfers = IotaFlashBridge.close(user.getFlash().getSettlementAddresses(), user.getFlash().getDeposits()); } else { newTransfers = IotaFlashBridge.prepare( user.getFlash().getSettlementAddresses(), @@ -23,6 +24,7 @@ public class Helpers { user.getUserIndex(), transfers ); + } ArrayList bundles = IotaFlashBridge.compose( @@ -42,6 +44,33 @@ public class Helpers { return IotaFlashBridge.sign(user.getFlash().getRoot(), user.getSeed(), bundles); } + public static ArrayList appliedSignatures(ArrayList bundles, ArrayList signatures) { + ArrayList clonedBundles = clone(bundles); + bundles.clone(); + + for (int i = 0; i < bundles.size(); i++) { + Signature sig = signatures.get(i); + Bundle b = bundles.get(i); + if (sig == null) { + continue; + } + + ArrayList transactions = b.getBundles(); + String addy = transactions.stream().filter(tx -> tx.getValue() < 0).findFirst().get().getAddress(); + List tmp = transactions.stream() + .filter(tx -> tx.getAddress().equals(addy)) + .collect(Collectors.toList()); + + tmp = tmp.subList(sig.getIndex(), sig.getIndex() + sig.getSignatureFragments().size()); + + for (int j = 0; j < tmp.size(); j++) { + tmp.get(j).setSignatureFragments(sig.getSignatureFragments().get(j)); + } + } + + return clonedBundles; + } + public static void applyTransfers(UserObject user, ArrayList bundles) { IotaFlashBridge.applayTransfers( user.getFlash().getRoot(), @@ -52,4 +81,12 @@ public class Helpers { bundles ); } + + public static ArrayList clone(ArrayList bundles) { + ArrayList clonedBundles = new ArrayList<>(); + for (Bundle b : bundles) { + clonedBundles.add(b.clone()); + } + return clonedBundles; + } } diff --git a/src/main/java/IotaFlashBridge.java b/src/main/java/IotaFlashBridge.java index 0eddb4b..ee1143c 100644 --- a/src/main/java/IotaFlashBridge.java +++ b/src/main/java/IotaFlashBridge.java @@ -25,6 +25,14 @@ public class IotaFlashBridge { engine.executeVoidScript(file); multisig = (V8Object) engine.executeScript("iotaFlash.multisig"); transfer = (V8Object) engine.executeScript("iotaFlash.transfer"); + + Model.Console console = new Model.Console(); + V8Object v8Console = new V8Object(engine); + engine.add("console", v8Console); + v8Console.registerJavaMethod(console, "log", "log", new Class[] { String.class }); + v8Console.registerJavaMethod(console, "err", "err", new Class[] { String.class }); + v8Console.release(); + engine.executeScript("console.log('Connected JS console to V8Engine output.');"); } /** @@ -93,11 +101,8 @@ public class IotaFlashBridge { V8Object ret = multisig.executeObjectFunction("updateLeafToRoot", params); int generate = ret.getInteger("generate"); - Map multiSigMap = V8ObjectUtils.toMap((V8Object) ret.getObject("multisig")); - // Parse result into Java Obj. - String addr = (String) multiSigMap.get("address"); - int secSum = (Integer) multiSigMap.get("securitySum"); - MultisigAddress multisig = new MultisigAddress(addr, secSum); + V8Object multisigObject = (V8Object) ret.getObject("multisig"); + MultisigAddress multisig = V8Converter.multisigAddressFromV8Object(multisigObject); return new CreateTransactionHelperObject(generate, multisig); } @@ -110,7 +115,7 @@ public class IotaFlashBridge { * @param transfers array of all transfers (value, address) pairs * @return */ - public static ArrayList prepare(ArrayList settlementAddresses, ArrayList deposits, int index, ArrayList transfers) { + public static ArrayList prepare(ArrayList settlementAddresses, ArrayList deposits, int index, ArrayList transfers) { // Now put all params into JS ready array. List params = new ArrayList<>(); @@ -121,21 +126,28 @@ public class IotaFlashBridge { // Call js function. V8Array ret = transfer.executeArrayFunction("prepare", V8ObjectUtils.toV8Array(engine, params)); - List transfersReturnJS = V8ObjectUtils.toList(ret); + return V8Converter.transferListFromV8Array(ret); + } - ArrayList returnTransfers = new ArrayList<>(); - for (Object b: transfersReturnJS) { - Map values = (Map) b; - String obsoleteTag = (String) values.get("obsoleteTag"); - String address = (String) values.get("address"); - Integer value = (Integer) values.get("value"); + /** + * + * @param settlementAddresses + * @param deposits + * @return + */ + public static ArrayList close(ArrayList settlementAddresses, ArrayList deposits) { + V8Array saJS = V8ObjectUtils.toV8Array(engine, settlementAddresses); + // Deposits + V8Array depositsJS = V8ObjectUtils.toV8Array(engine, deposits); - returnTransfers.add(new Transaction(address, value, "", "", 0)); - } + // Add to prams + ArrayList paramsObj = new ArrayList(); - // Call js. - return returnTransfers; + paramsObj.add(saJS); + paramsObj.add(depositsJS); + V8Array res = transfer.executeArrayFunction("close", V8ObjectUtils.toV8Array(engine, paramsObj)); + return V8Converter.transferListFromV8Array(res); } /** @@ -146,7 +158,7 @@ public class IotaFlashBridge { * @param root * @param remainderAddress * @param history - * @param transactions + * @param transfers * @param close * @return */ @@ -156,7 +168,7 @@ public class IotaFlashBridge { MultisigAddress root, MultisigAddress remainderAddress, ArrayList history, - ArrayList transactions, + ArrayList transfers, boolean close) { @@ -170,11 +182,10 @@ public class IotaFlashBridge { params.add(V8Converter.multisigToV8Object(engine, root)); params.add(V8Converter.multisigToV8Object(engine, remainderAddress)); params.add(V8Converter.bundleListToV8Array(engine, history)); - params.add(V8Converter.transactionListToV8Array(engine, transactions)); + params.add(V8Converter.transferListToV8Array(engine, transfers)); // Call js function. V8Array ret = transfer.executeArrayFunction("compose", V8ObjectUtils.toV8Array(engine, params)); - List transfersReturnJS = V8ObjectUtils.toList(ret); return V8Converter.bundleListFromV8Array(ret); } @@ -193,8 +204,9 @@ public class IotaFlashBridge { List params = new ArrayList<>(); params.add(V8Converter.multisigToV8Object(engine, root)); params.add(seed); - params.add(V8Converter.bundleListToV8Array(engine, bundles)); + // Create bundle nested list by incoding all bundles + params.add(V8Converter.bundleListToV8Array(engine, bundles)); V8Array returnArray = transfer.executeArrayFunction("sign", V8ObjectUtils.toV8Array(engine, params)); return V8Converter.v8ArrayToSignatureList(returnArray); @@ -256,26 +268,6 @@ public class IotaFlashBridge { transfer.executeFunction("applyTransfers", V8ObjectUtils.toV8Array(engine, params)); } - /** - * - * @param settlementAddresses - * @param deposits - * @return - */ - public static Object close(ArrayList settlementAddresses, ArrayList deposits) { - V8Array saJS = V8ObjectUtils.toV8Array(engine, settlementAddresses); - // Deposits - V8Array depositsJS = V8ObjectUtils.toV8Array(engine, deposits); - - // Add to prams - ArrayList paramsObj = new ArrayList(); - - paramsObj.add(saJS); - paramsObj.add(depositsJS); - V8Object res = transfer.executeObjectFunction("close", V8ObjectUtils.toV8Array(engine, paramsObj)); - return res; - } - /// Utils /** diff --git a/src/main/java/Main.java b/src/main/java/Main.java index fc08ca4..03ea3d1 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -72,7 +72,7 @@ public class Main { // Build flash trees for (int i = 1; i < oneMultisigs.size(); i++) { - System.out.println("Adding child (" + oneMultisigs.get(i).toString() + ") to root :" + oneMultisigs.get(i - 1).toString() ); + System.out.println(oneMultisigs.get(i - 1).toString() + " -> " + oneMultisigs.get(i).toString()); oneMultisigs.get(i - 1).push(oneMultisigs.get(i)); } @@ -100,13 +100,12 @@ public class Main { ArrayList transfers = new ArrayList<>(); transfers.add(new Transfer(twoSettlement, 200)); - System.out.println("Creating a transaction"); + System.out.println(oneFlash); + + System.out.println("Creating a transaction: 200 to " + twoSettlement); ArrayList bundles = Helpers.createTransaction(oneFlash, transfers, false); - System.out.println("createTransaction completed"); - for (Bundle b: bundles) { - System.out.println(b.toString()); - } + System.out.println("[SUCCESS] createTransaction completed"); // Sign the bundles. // Get signatures for the bundles @@ -115,12 +114,20 @@ public class Main { // Generate USER TWO'S Singatures ArrayList twoSignatures = Helpers.signTransaction(twoFlash, bundles); + System.out.println("[SUCCESS] Created signatures for users."); + // Sign bundle with your USER ONE'S signatures ArrayList signedBundles = IotaFlashBridge.appliedSignatures(bundles, oneSignatures); + System.out.println("[SUCCESS] Parial applied Signature for User one on transfer bundle"); + + // ADD USER TWOS'S signatures to the partially signed bundles signedBundles = IotaFlashBridge.appliedSignatures(signedBundles, twoSignatures); + System.out.println("[SUCCESS] Signed bundle bu second user. Bundle ready."); + + ///////////////////////////////// /// APPLY SIGNED BUNDLES @@ -134,9 +141,55 @@ public class Main { Helpers.applyTransfers(twoFlash, signedBundles); // Save latest channel bundles twoFlash.setBundles(signedBundles); + System.out.println("[SUCCESS] Apply Transfer to flash channel."); + System.out.println("Transaction Applied!"); + System.out.println( + "Transactable tokens: " + + oneFlash.getFlash().getDeposits().stream().mapToInt(v -> v.intValue()).sum() + ); + System.out.println("Closing channel... not yet working..."); +/* + + // Supplying the CORRECT varibles to create a closing bundle + bundles = Helpers.createTransaction( + oneFlash, + oneFlash.getFlash().getSettlementAddresses(), + true + ); + + ///////////////////////////////// + /// SIGN BUNDLES + + // Get signatures for the bundles + oneSignatures = Helpers.signTransaction(oneFlash, bundles) + + // Generate USER TWO'S Singatures + twoSignatures = Helpers.signTransaction(twoFlash, bundles) + + // Sign bundle with your USER ONE'S signatures + signedBundles = transfer.appliedSignatures(bundles, oneSignatures) + + // ADD USER TWOS'S signatures to the partially signed bundles + signedBundles = transfer.appliedSignatures(signedBundles, twoSignatures) + + ///////////////////////////////// + /// APPLY SIGNED BUNDLES + + // Apply transfers to User ONE + oneFlash = Helpers.applyTransfers(oneFlash, signedBundles) + // Save latest channel bundles + oneFlash.bundles = signedBundles + + // Apply transfers to User TWO + twoFlash = Helpers.applyTransfers(twoFlash, signedBundles) + // Save latest channel bundles + twoFlash.bundles = signedBundles + + console.log("Channel Closed") + console.log("Final Bundle to be attached: ")*/ } private static void setupUser(UserObject user, int TREE_DEPTH) { diff --git a/src/main/java/Model/Bundle.java b/src/main/java/Model/Bundle.java index d5946fd..61645ba 100644 --- a/src/main/java/Model/Bundle.java +++ b/src/main/java/Model/Bundle.java @@ -19,6 +19,16 @@ public class Bundle { this.bundles = new ArrayList<>(); } + @Override + public String toString() { + String out = ""; + for (Transaction t: bundles) { + out += t.toString(); + out += "\n"; + } + return out; + } + public Map toMap() { Map map = new HashMap(); List bundleList = new ArrayList(); @@ -33,6 +43,13 @@ public class Bundle { return bundles; } + public Bundle clone() { + ArrayList clonedTransactions = new ArrayList<>(); + for (Transaction t: bundles) { + clonedTransactions.add(t.clone()); + } + return new Bundle(clonedTransactions); + } } diff --git a/src/main/java/Model/Console.java b/src/main/java/Model/Console.java new file mode 100644 index 0000000..73af927 --- /dev/null +++ b/src/main/java/Model/Console.java @@ -0,0 +1,13 @@ +package Model; + + +public class Console { + + public void log(final String message) { + System.out.println("[INFO] " + message); + } + + public void err(final String message) { + System.out.println("[ERROR] " + message); + } +} diff --git a/src/main/java/Model/FlashObject.java b/src/main/java/Model/FlashObject.java index e4f5eff..b8e30c3 100644 --- a/src/main/java/Model/FlashObject.java +++ b/src/main/java/Model/FlashObject.java @@ -6,11 +6,12 @@ public class FlashObject { int signersCount = 2; int balance; ArrayList settlementAddresses; - MultisigAddress root; - MultisigAddress remainderAddress; ArrayList deposits; // Clone correctly ArrayList outputs = new ArrayList(); ArrayList transfers = new ArrayList(); + MultisigAddress root; + MultisigAddress remainderAddress; + public FlashObject(int signersCount, int balance, ArrayList deposits) { this.signersCount = signersCount; @@ -18,6 +19,35 @@ public class FlashObject { this.deposits = deposits; } + @Override + public String toString() { + String out = ""; + out += "signersCount: " + signersCount + "\n"; + out += "balance: " + balance + "\n"; + out += "settlementAddresses: " + "\n"; + for (String b: settlementAddresses) { + out += "\t" + b + "\n"; + } + out += "deposits: " + "\n"; + for (Integer b: deposits) { + out += "\t" + b + "\n"; + } + + out += "outputs: " + "\n"; + for (Bundle b: outputs) { + out += "\t" + b.toString() + "\n"; + } + + out += "transfers: " + "\n"; + for (Bundle b: transfers) { + out += "\t" + b.toString() + "\n"; + } + out += "remainderAddress: " + remainderAddress.toString() + "\n"; + out += "root: " + root.toString() + "\n"; + + return out; + } + public int getSignersCount() { return signersCount; } diff --git a/src/main/java/Model/MultisigAddress.java b/src/main/java/Model/MultisigAddress.java index 8a994a8..a9d7062 100644 --- a/src/main/java/Model/MultisigAddress.java +++ b/src/main/java/Model/MultisigAddress.java @@ -15,7 +15,7 @@ public class MultisigAddress { private int securitySum; private int index; private int signingIndex; - private int security; + private int security = 2; private ArrayList children; private ArrayList bundles; @@ -27,6 +27,13 @@ public class MultisigAddress { } + public MultisigAddress(String address, int securitySum, ArrayList children) { + this.address = address; + this.securitySum = securitySum; + this.children = children; + this.bundles = new ArrayList(); + } + public void push(MultisigAddress addr) { children.add(addr); } @@ -74,7 +81,9 @@ public class MultisigAddress { Map map = new HashMap(); map.put("address", getAddress()); map.put("securitySum", getSecuritySum()); - + map.put("index", getIndex()); + map.put("signingIndex", getSigningIndex()); + map.put("security", security); List childrenList = new ArrayList(); for (MultisigAddress ma: children) { childrenList.add(ma.toMap()); @@ -96,6 +105,10 @@ public class MultisigAddress { @Override public String toString() { - return "{'address':'" + address + "', securitySum:" + securitySum + ", signingIndex: " + signingIndex + "}"; + String out = "{ \n address':'" + address + "' \n, securitySum:" + securitySum + "\n, signingIndex: " + signingIndex + " \n"; + for (MultisigAddress addr: children) { + out += addr.toString(); + } + return out; } } \ No newline at end of file diff --git a/src/main/java/Model/Signature.java b/src/main/java/Model/Signature.java index ce2221d..a8a2b9d 100644 --- a/src/main/java/Model/Signature.java +++ b/src/main/java/Model/Signature.java @@ -9,7 +9,8 @@ import java.util.List; * @author Adrian **/ public class Signature { - + private int index; + private String bundle; private String address; private List signatureFragments; @@ -55,4 +56,38 @@ public class Signature { public void setSignatureFragments(List signatureFragments) { this.signatureFragments = signatureFragments; } -} \ No newline at end of file + + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public String getBundle() { + return bundle; + } + + public void setBundle(String bundle) { + this.bundle = bundle; + } + + @Override + public String toString() { + String out = "{ \n" + + " \tindex:" + index + ", " + + " \n\tbundle: " + bundle + ", " + + " \n\taddress:" + address + ","; + + out += "\n\t[ \n"; + for (String sf : signatureFragments) { + out += "\n\t" + sf + ","; + } + out += " ]"; + out += "\n}"; + return out; + } +} + diff --git a/src/main/java/Model/Transaction.java b/src/main/java/Model/Transaction.java index 27a2244..a6a0e6a 100644 --- a/src/main/java/Model/Transaction.java +++ b/src/main/java/Model/Transaction.java @@ -4,26 +4,27 @@ import java.util.HashMap; import java.util.Map; public class Transaction { - private int timestamp; + private String hash; + private String signatureFragments; private String address; - private int value; + private long value; private String obsoleteTag; + private long timestamp; + private long currentIndex; + private long lastIndex; + private String bundle; + private String trunkTransaction; + private String branchTransaction; + private String nonce; + private Boolean persistence; + private long attachmentTimestamp; private String tag; + private long attachmentTimestampLowerBound; + private long attachmentTimestampUpperBound; - // Model.Signature stuff - private String bundle = ""; - private String signatureMessageFragment = ""; - private String trunkTransaction = ""; - private String branchTransaction = ""; - - private String attachmentTimestamp = ""; - private String attachmentTimestampUpperBound = ""; - private String attachmentTimestampLowerBound = ""; - - private String nonce = ""; // Unsigned constructor - public Transaction(String address, int value, String obsoleteTag, String tag, int timestamp) { + public Transaction(String address, int value, String obsoleteTag, String tag, Integer timestamp) { this.address = address; this.value = value; this.obsoleteTag = obsoleteTag; @@ -31,67 +32,95 @@ public class Transaction { this.timestamp = timestamp; } - // Signed constructor - public Transaction(String address, - String bundle, - int value, - String obsoleteTag, - String tag, - int timestamp, - String signatureMessageFragment, - String trunkTransaction, - String branchTransaction, + public Transaction(String signatureFragments, Long currentIndex, Long lastIndex, String nonce, + String hash, String obsoleteTag, Long timestamp, String trunkTransaction, + String branchTransaction, String address, Long value, String bundle, String tag, + Long attachmentTimestamp, Long attachmentTimestampLowerBound, Long attachmentTimestampUpperBound) { - String attachmentTimestamp, - String attachmentTimestampUpperBound, - String attachmentTimestampLowerBound, - - String nonce - ) { + this.hash = hash; + this.obsoleteTag = obsoleteTag; + this.signatureFragments = signatureFragments; this.address = address; this.value = value; - this.obsoleteTag = obsoleteTag; - this.tag = tag; this.timestamp = timestamp; - this.signatureMessageFragment = signatureMessageFragment; + this.currentIndex = currentIndex; + this.lastIndex = lastIndex; + this.bundle = bundle; this.trunkTransaction = trunkTransaction; this.branchTransaction = branchTransaction; - + this.tag = tag; this.attachmentTimestamp = attachmentTimestamp; - this.attachmentTimestampUpperBound = attachmentTimestampUpperBound; this.attachmentTimestampLowerBound = attachmentTimestampLowerBound; - + this.attachmentTimestampUpperBound = attachmentTimestampUpperBound; this.nonce = nonce; } - public int getValue() { + + public String getSignatureFragments() { + return signatureFragments; + } + + public void setSignatureFragments(String signatureFragments) { + this.signatureFragments = signatureFragments; + } + + public long getValue() { return value; } + public String getAddress() { return address; } public Map toMap() { Map map = new HashMap(); + if (hash != null && !hash.equals("")) { + map.put("hash", hash); + } + map.put("signatureMessageFragment", signatureFragments); map.put("address", address); map.put("value", value); map.put("obsoleteTag", obsoleteTag); - map.put("tag", tag); + map.put("currentIndex", currentIndex); map.put("timestamp", timestamp); - map.put("signatureMessageFragment", signatureMessageFragment); + map.put("lastIndex", lastIndex); + map.put("bundle", bundle); map.put("trunkTransaction", trunkTransaction); map.put("branchTransaction", branchTransaction); - map.put("attachmentTimestamp", attachmentTimestamp); - map.put("attachmentTimestampLowerBound", attachmentTimestampLowerBound); - map.put("attachmentTimestampUpperBound", attachmentTimestampUpperBound); + map.put("nonce", nonce); + map.put("attachmentTimestamp", String.valueOf(attachmentTimestamp)); + map.put("tag", tag); + map.put("attachmentTimestampLowerBound", String.valueOf(attachmentTimestampLowerBound)); + map.put("attachmentTimestampUpperBound", String.valueOf(attachmentTimestampUpperBound)); return map; } + public Transaction clone() { + return new Transaction( + this.signatureFragments, + this.currentIndex, + this.lastIndex, + this.nonce, + this.hash, + this.obsoleteTag, + this.timestamp, + this.trunkTransaction, + this.branchTransaction, + this.address, + this.value, + this.bundle, + this.tag, + this.attachmentTimestamp, + this.attachmentTimestampLowerBound, + this.attachmentTimestampUpperBound + ); + } + public String toString() { Map mapObj = toMap(); String value = "{"; for (Map.Entry entry: mapObj.entrySet()) { - value += "'" + entry.getKey() + "':'" + entry.getValue().toString() + "', "; + value += "'" + entry.getKey() + "':'" + entry.getValue().toString() + "', \n"; } value += "}"; return value; diff --git a/src/main/java/Model/Transfer.java b/src/main/java/Model/Transfer.java index 4e929e6..ed0f388 100644 --- a/src/main/java/Model/Transfer.java +++ b/src/main/java/Model/Transfer.java @@ -1,34 +1,200 @@ package Model; +import com.google.gson.Gson; + import java.util.HashMap; import java.util.Map; public class Transfer { - private String address; - private int value; - public Transfer(String address, int value) { + private String timestamp; + private String address; + private String hash; + private Boolean persistence; + private long value; + private String message; + private String tag; + + /** + * Initializes a new instance of the Transfer class. + */ + public Transfer(String timestamp, String address, String hash, Boolean persistence, long value, String message, + String tag) { + this.timestamp = timestamp; this.address = address; + this.hash = hash; + this.persistence = persistence; this.value = value; + this.message = message; + this.tag = tag; } + /** + * Initializes a new instance of the Transfer class. + */ + public Transfer(String address, long value) { + this.address = address; + this.value = value; + this.message = ""; + this.tag = ""; + } + + /** + * Initializes a new instance of the Transfer class. + */ + public Transfer(String address, long value, String message, String tag) { + this.address = address; + this.value = value; + this.message = message; + this.tag = tag; + } + + /** + * Returns a Json Object that represents this object. + * + * @return Returns a string representation of this object. + */ + @Override + public String toString() { + return new Gson().toJson(this); + } + + /** + * Get the address. + * + * @return The address. + */ public String getAddress() { return address; } - public int getValue() { + /** + * Set the address. + * + * @param address The address. + */ + public void setAddress(String address) { + this.address = address; + } + + /** + * Get the hash. + * + * @return The hash. + */ + public String getHash() { + return hash; + } + + /** + * Set the hash. + * + * @param hash The hash. + */ + public void setHash(String hash) { + this.hash = hash; + } + + /** + * Get the persistence. + * + * @return The persistence. + */ + public Boolean getPersistence() { + return persistence; + } + + /** + * Set the persistence. + * + * @param persistence The persistence. + */ + public void setPersistence(Boolean persistence) { + this.persistence = persistence; + } + + /** + * Get the timestamp. + * + * @return The timestamp. + */ + public String getTimestamp() { + return timestamp; + } + + /** + * Set the timestamp. + * + * @param timestamp The timestamp in seconds. + */ + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + /** + * Get the value. + * + * @return The value. + */ + public long getValue() { return value; } - @Override - public String toString() { - return "{'address':'" + getAddress() + "','value':" + getValue() +" }"; + /** + * Set the value. + * + * @param value The value. + */ + public void setValue(long value) { + this.value = value; + } + + /** + * Get the message. + * + * @return The message. + */ + public String getMessage() { + return message; + } + + /** + * Set the message. + * + * @param message The message trytes encoded. + */ + public void setMessage(String message) { + this.message = message; + } + + /** + * Get the tag. + * + * @return The tag. + */ + public String getTag() { + return tag; + } + + /** + * Set the tag. + * + * @param tag The tag max 27 trytes encoded. + */ + public void setTag(String tag) { + this.tag = tag; } public Map toMap() { Map map = new HashMap(); + map.put("timestamp", getTimestamp()); map.put("address", getAddress()); + map.put("hash", getHash()); + map.put("persistance", getPersistence()); map.put("value", getValue()); + map.put("message", getMessage()); + map.put("tag", getTag()); return map; + } } \ No newline at end of file diff --git a/src/main/java/Model/UserObject.java b/src/main/java/Model/UserObject.java index 39b5946..e5f6f3d 100644 --- a/src/main/java/Model/UserObject.java +++ b/src/main/java/Model/UserObject.java @@ -1,5 +1,6 @@ package Model; +import java.lang.reflect.Field; import java.util.ArrayList; public class UserObject { @@ -28,14 +29,39 @@ public class UserObject { partialDigests.add(digest); } + @Override + public String toString() { + String out = ""; + out += "userIndex: " + userIndex + "\n"; + out += "seed: " + seed + "\n"; + out += "index: " + index + "\n"; + out += "security: " + getSecurity() + "\n"; + out += "depth: " + depth + "\n"; + out += "bundles: " + "\n"; + for (Bundle b: bundles) { + out += "\t" + b.toString() + "\n"; + } + out += "partialDigests: " + "\n"; + for (Digest d: partialDigests) { + out += "\t" + d.toString() + "\n"; + } + out += "multisigDigests: " + "\n"; + for (MultisigAddress m: multisigDigests) { + out += "\t" + m.toString() + "\n"; + } + out += "Flash: " + "\n"; + out += flash.toString(); - + return out; + } /** * * Getters and Setters */ + + public void setMultisigDigests(ArrayList multisigDigests) { this.multisigDigests = multisigDigests; } diff --git a/src/main/java/V8Converter.java b/src/main/java/V8Converter.java index 6169277..672374e 100644 --- a/src/main/java/V8Converter.java +++ b/src/main/java/V8Converter.java @@ -2,8 +2,12 @@ import Model.*; import com.eclipsesource.v8.V8; import com.eclipsesource.v8.V8Array; import com.eclipsesource.v8.V8Object; +import com.eclipsesource.v8.V8ResultUndefined; import com.eclipsesource.v8.utils.V8ObjectUtils; +import com.sun.org.apache.xpath.internal.operations.Mult; +import sun.rmi.server.InactiveGroupException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -15,12 +19,19 @@ public class V8Converter { ArrayList signatures = new ArrayList<>(); for (Object o: V8ObjectUtils.toList(array)) { Map returnValues = (Map) o; + String addr = (String) returnValues.get("address"); + Integer index = (Integer) returnValues.get("index"); + String bundle = (String) returnValues.get("bundle"); ArrayList signatureFragments = (ArrayList) returnValues.get("signatureFragments"); + Signature sig = new Signature(); sig.setAddress(addr); sig.setSignatureFragments(signatureFragments); + sig.setIndex(index); + sig.setBundle(bundle); signatures.add(sig); + } return signatures; @@ -44,6 +55,36 @@ public class V8Converter { return V8ObjectUtils.toV8Array(engine, bundleTmp); } + public static MultisigAddress multisigAddressFromV8Object(V8Object input) { + Map multiSigMap = V8ObjectUtils.toMap(input); + return multisigAddressFromPropertyMap(multiSigMap); + } + + public static MultisigAddress multisigAddressFromPropertyMap(Map propMap) { + // Parse result into Java Obj. + String addr = (String) propMap.get("address"); + int secSum = (Integer) propMap.get("securitySum"); + + + ArrayList children = new ArrayList<>(); + + for (Object child: (ArrayList) propMap.get("children")) { + Map childPropMap = (Map) child; + children.add(multisigAddressFromPropertyMap(childPropMap)); + } + + MultisigAddress multisig = new MultisigAddress(addr, secSum, children); + + if (propMap.get("index") != null) { + multisig.setIndex((Integer) propMap.get("index")); + } + if (propMap.get("signingIndex") != null) { + multisig.setSigningIndex((Integer) propMap.get("signingIndex")); + } + + return multisig; + } + public static ArrayList bundleListFromV8Array(V8Array input) { List inputList = V8ObjectUtils.toList(input); // Parse return as array of bundles @@ -66,6 +107,8 @@ public class V8Converter { List returnArr = new ArrayList<>(); for (Signature sig: signatures) { Map signatureMap = new HashMap(); + signatureMap.put("bundle", sig.getBundle()); + signatureMap.put("index", sig.getIndex()); signatureMap.put("address", sig.getAddress()); signatureMap.put("signatureFragments", sig.getSignatureFragments()); returnArr.add(signatureMap); @@ -73,6 +116,48 @@ public class V8Converter { return V8ObjectUtils.toV8Array(engine, returnArr); } + + public static ArrayList transferListFromV8Array(V8Array input) { + ArrayList transfers = new ArrayList<>(); + List jsTransferList = V8ObjectUtils.toList(input); + if (jsTransferList != null) { + for (Object obj: jsTransferList) { + transfers.add(transferFromObject(obj)); + } + } + + return transfers; + } + + public static Transfer transferFromObject(Object input) { + if (input instanceof Map) { + Map values = (Map) input; + String obsoleteTag = (String) values.get("obsoleteTag"); + String address = (String) values.get("address"); + Long value = parseLongFromObject(values.get("value")); + if (values.get("timestamp") instanceof String) { + String timestamp = (String) values.get("timestamp"); + String hash = (String) values.get("hash"); + Boolean persistance = (Boolean) values.get("persistance"); + String message = (String) values.get("message"); + String tag = (String) values.get("tag"); + return new Transfer( + timestamp, + address, + hash, + persistance, + value, + message, + tag + ); + } else { + System.out.println("[WARN] Could not find key for full transfer creating slim transfer object"); + return new Transfer(address, value); + } + } + return null; + } + public static V8Array transferListToV8Array(V8 engine, ArrayList transfers) { List transferObj = new ArrayList(); for (Transfer t: transfers) { @@ -93,38 +178,53 @@ public class V8Converter { public static Transaction transactionFromObject(Object input) { Map bundleData = (Map) input; String signatureMessageFragment = (String) bundleData.get("signatureMessageFragment"); - String bundle = (String) bundleData.get("bundle"); - String address = (String) bundleData.get("address"); - String attachmentTimestampLowerBound = (String) bundleData.get("attachmentTimestampLowerBound"); - String attachmentTimestampUpperBound = (String) bundleData.get("attachmentTimestampUpperBound"); - String trunkTransaction = (String) bundleData.get("trunkTransaction"); - String attachmentTimestamp = (String) bundleData.get("attachmentTimestamp"); - Integer timestamp = (Integer) bundleData.get("timestamp"); - String tag = (String) bundleData.get("tag"); - String branchTransaction = (String) bundleData.get("branchTransaction"); + Long currentIndex = parseLongFromObject(bundleData.get("currentIndex")); + Long lastIndex = parseLongFromObject(bundleData.get("lastIndex")); String nonce = (String) bundleData.get("nonce"); + String hash = ""; + if (bundleData.get("hash") instanceof String) { + hash = (String) bundleData.get("hash"); + } String obsoleteTag = (String) bundleData.get("obsoleteTag"); - - Integer currentIndex = (Integer) bundleData.get("currentIndex"); - Integer value = (Integer) bundleData.get("value"); - Integer lastIndex = (Integer) bundleData.get("lastIndex"); - + Long timestamp = parseLongFromObject(bundleData.get("timestamp")); + String trunkTransaction = (String) bundleData.get("trunkTransaction"); + String branchTransaction = (String) bundleData.get("branchTransaction"); + String address = (String) bundleData.get("address"); + Long value = parseLongFromObject(bundleData.get("value")); + String bundle = (String) bundleData.get("bundle"); + String tag = (String) bundleData.get("tag"); + Long attachmentTimestamp = parseLongFromObject(bundleData.get("attachmentTimestamp")); + Long attachmentTimestampLowerBound = parseLongFromObject(bundleData.get("attachmentTimestampLowerBound")); + Long attachmentTimestampUpperBound = parseLongFromObject(bundleData.get("attachmentTimestampUpperBound")); Transaction parsedTransaction = new Transaction( - address, - bundle, - value.intValue(), - obsoleteTag, - tag, - timestamp, signatureMessageFragment, + currentIndex, + lastIndex, + nonce, + hash, + obsoleteTag, + timestamp, trunkTransaction, branchTransaction, - + address, + value, + bundle, + tag, attachmentTimestamp, - attachmentTimestampUpperBound, attachmentTimestampLowerBound, - nonce + attachmentTimestampUpperBound ); return parsedTransaction; } + + public static Long parseLongFromObject(Object value) { + if (value instanceof String) { + return Long.parseLong((String) value); + } + if (value instanceof Integer) { + return new Long((Integer) value); + } + + return new Long(0); + } }