mirror of
https://github.com/gosticks/iota.flash.js-java-wrapper.git
synced 2026-06-28 15:50:03 +00:00
Fixed conversion errors, added dynamich branch generation, refactor and code cleanup.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package iotaFlashWrapper;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.operations.Mult;
|
||||
import iotaFlashWrapper.Model.*;
|
||||
|
||||
|
||||
@@ -8,89 +9,218 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Helpers {
|
||||
public static ArrayList<Bundle> createTransaction(UserObject user, ArrayList<Transfer> transfers, boolean shouldClose) {
|
||||
CreateTransactionHelperObject toUse = IotaFlashBridge.updateLeafToRoot(user.getFlash().getRoot());
|
||||
if (toUse.getGenerate() != 0) {
|
||||
// TODO: tell the server to gen new address.
|
||||
System.out.println("No more addresses in channel.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a transaction object. The object contains the address to use and if required the number of new addresses to generate
|
||||
* @param root multisig address at the top of the tree
|
||||
* @return Transaction object with address and number of addresses to create.
|
||||
*/
|
||||
public static CreateTransactionHelperObject getTransactionHelper(MultisigAddress root) {
|
||||
return IotaFlashBridge.updateLeafToRoot(root);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param transfers
|
||||
* @param toUse Transaction helper object
|
||||
* @param user
|
||||
* @param shouldClose
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<Bundle> createTransaction(ArrayList<Transfer> transfers, CreateTransactionHelperObject toUse, UserObject user, boolean shouldClose) {
|
||||
// System.out.println("Creating a transaction of" + transfers.getValue() + " to " + transfers.getAddress());
|
||||
System.out.println("[INFO]: using address " + toUse.getAddress().getAddress() + ", with boundle count" + toUse.getAddress().getBundles().size());
|
||||
|
||||
ArrayList<Transfer> newTransfers;
|
||||
FlashObject flash = user.getFlash();
|
||||
|
||||
if (shouldClose) {
|
||||
newTransfers = IotaFlashBridge.close(user.getFlash().getSettlementAddresses(), user.getFlash().getDeposits());
|
||||
newTransfers = IotaFlashBridge.close(flash.getSettlementAddresses(), flash.getDeposits());
|
||||
} else {
|
||||
// Prepare a new transaction.
|
||||
newTransfers = IotaFlashBridge.prepare(
|
||||
user.getFlash().getSettlementAddresses(),
|
||||
user.getFlash().getDeposits(),
|
||||
flash.getSettlementAddresses(),
|
||||
flash.getDeposits(),
|
||||
user.getUserIndex(),
|
||||
transfers
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// Compose the transaction. This may also add some management transactions (moving remainder tokens.)
|
||||
ArrayList<Bundle> bundles = IotaFlashBridge.compose(
|
||||
user.getFlash().getBalance(),
|
||||
user.getFlash().getDeposits(),
|
||||
user.getFlash().getOutputs(),
|
||||
flash.getBalance(),
|
||||
flash.getDeposits(),
|
||||
flash.getOutputs(),
|
||||
toUse.getAddress(),
|
||||
user.getFlash().getRemainderAddress(),
|
||||
user.getFlash().getTransfers(),
|
||||
flash.getRemainderAddress(),
|
||||
flash.getTransfers(),
|
||||
newTransfers,
|
||||
shouldClose
|
||||
);
|
||||
return bundles;
|
||||
|
||||
System.out.println("[SUCCESS] Created signatures for user" + user.getUserIndex());
|
||||
// Apply the signature of the transaction creater to the current transactions bundle.
|
||||
ArrayList<Signature> signatures = IotaFlashBridge.sign(toUse.getAddress(), user.getSeed(), bundles);
|
||||
|
||||
System.out.println("[SUCCESS] Parial applied Signature for user" + user.getUserIndex() + " on transfer bundle");
|
||||
// Sign bundle with your USER ONE'S signatures
|
||||
return IotaFlashBridge.appliedSignatures(bundles, signatures);
|
||||
}
|
||||
|
||||
public static ArrayList<Signature> signTransaction(UserObject user, ArrayList<Bundle> bundles) {
|
||||
return IotaFlashBridge.sign(user.getFlash().getRoot(), user.getSeed(), bundles);
|
||||
}
|
||||
//
|
||||
// public static ArrayList<Bundle> appliedSignatures(ArrayList<Bundle> bundles, ArrayList<Signature> signatures) {
|
||||
// ArrayList<Bundle> 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<Transaction> transactions = b.getBundles();
|
||||
// String addy = transactions.stream().filter(tx -> tx.getValue() < 0).findFirst().get().getAddress();
|
||||
// List<Transaction> 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;
|
||||
// }
|
||||
/**
|
||||
*
|
||||
* Tree management.
|
||||
*
|
||||
*/
|
||||
|
||||
public static void applyTransfers(UserObject user, ArrayList<Bundle> bundles) {
|
||||
FlashObject flash = IotaFlashBridge.applyTransfersToUser(user, bundles);
|
||||
user.setFlash(flash);
|
||||
// IotaFlashBridge.applyTransfers(
|
||||
// user.getFlash().getRoot(),
|
||||
// user.getFlash().getDeposits(),
|
||||
// user.getFlash().getOutputs(),
|
||||
// user.getFlash().getRemainderAddress(),
|
||||
// user.getFlash().getTransfers(),
|
||||
// bundles
|
||||
// );
|
||||
}
|
||||
|
||||
public static ArrayList<Bundle> clone(ArrayList<Bundle> bundles) {
|
||||
ArrayList<Bundle> clonedBundles = new ArrayList<>();
|
||||
for (Bundle b : bundles) {
|
||||
clonedBundles.add(b.clone());
|
||||
/**
|
||||
*
|
||||
* @param user
|
||||
* @param toGenerate
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<Digest> getNewBranchDigests(UserObject user, int toGenerate) {
|
||||
ArrayList<Digest> digests = new ArrayList<>();
|
||||
for (int i = 0; i < toGenerate; i++) {
|
||||
Digest digest = IotaFlashBridge.getDigest(user.getSeed(), user.getIndex(), user.getSecurity());
|
||||
System.out.println("USING index for digest: " + user.getIndex() );
|
||||
user.incrementIndex();
|
||||
digests.add(digest);
|
||||
}
|
||||
return clonedBundles;
|
||||
return digests;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param oneDigests
|
||||
* @param twoDigests
|
||||
* @param user
|
||||
* @param address
|
||||
* @return
|
||||
*/
|
||||
public static MultisigAddress getNewBranch(ArrayList<Digest> oneDigests, ArrayList<Digest> twoDigests, UserObject user, MultisigAddress address) {
|
||||
ArrayList<ArrayList<Digest>> userDigestList = new ArrayList<>();
|
||||
userDigestList.add(oneDigests);
|
||||
userDigestList.add(twoDigests);
|
||||
ArrayList<MultisigAddress> multisigs = getMultisigsForUser(userDigestList, user);
|
||||
|
||||
System.out.println("[INFO]: Adding to address " + address.getAddress());
|
||||
|
||||
// Build flash trees
|
||||
for (int i = 1; i < multisigs.size(); i++) {
|
||||
multisigs.get(i - 1).push(multisigs.get(i));
|
||||
}
|
||||
|
||||
// Clone the address to avoid overwriting params.
|
||||
MultisigAddress output = address.clone();
|
||||
|
||||
// Add new multisigs to address.
|
||||
output.push(multisigs.get(0));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Digests and MultisigAddress creation
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates initial digests for a user. This will only create digests for a given TREE_DEPTH -> Digests.size == TREE_DEPTH + 1
|
||||
* Other transactions will be generated when required.
|
||||
* @param user user for which the digests should be generated
|
||||
* @param TREE_DEPTH number of initial digests to generate
|
||||
* @return digests for provided user.
|
||||
*/
|
||||
public static ArrayList<Digest> getDigestsForUser(UserObject user, int TREE_DEPTH) {
|
||||
ArrayList<Digest> digests = new ArrayList<>();
|
||||
// Create digests for the start of the channel
|
||||
for (int i = 0; i < TREE_DEPTH + 1; i++) {
|
||||
// Create new digest
|
||||
Digest digest = IotaFlashBridge.getDigest(
|
||||
user.getSeed(),
|
||||
user.getIndex(),
|
||||
user.getSecurity()
|
||||
);
|
||||
user.incrementIndex();
|
||||
System.out.println("Adding digest (" + digest.toString() + ") to user " + user.getUserIndex());
|
||||
// Increment key index
|
||||
|
||||
digests.add(digest);
|
||||
}
|
||||
return digests;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param allDigests
|
||||
* @param currentUser
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<MultisigAddress> getMultisigsForUser(ArrayList<ArrayList<Digest>> allDigests, UserObject currentUser) {
|
||||
|
||||
// Generate the first addresses
|
||||
ArrayList<MultisigAddress> multisigs = new ArrayList<MultisigAddress>();
|
||||
|
||||
// Loop for all digests.
|
||||
for (int index = 0; index < allDigests.get(0).size(); index++) {
|
||||
ArrayList<Digest> alignedDigests = new ArrayList<>();
|
||||
|
||||
int securitySum = 0;
|
||||
|
||||
// Loop for all users.
|
||||
for (int userIndex = 0; userIndex < allDigests.size(); userIndex++) {
|
||||
Digest digest = allDigests.get(userIndex).get(index);
|
||||
// Get array of digests for all users.
|
||||
alignedDigests.add(digest);
|
||||
securitySum += digest.getSecurity();
|
||||
}
|
||||
|
||||
// Create multisgAddr from digests.
|
||||
MultisigAddress multisigAddress = IotaFlashBridge.composeAddress(alignedDigests);
|
||||
|
||||
// Get digests data for current user.
|
||||
Digest digest = allDigests.get(currentUser.getUserIndex()).get(index);
|
||||
|
||||
multisigAddress.setIndex(digest.getIndex());
|
||||
multisigAddress.setSigningIndex(currentUser.getUserIndex() * digest.getSecurity());
|
||||
multisigAddress.setSecuritySum(securitySum);
|
||||
multisigAddress.setSecurity(digest.getSecurity());
|
||||
|
||||
System.out.println("Creating address " + multisigAddress.getAddress() + " index" + multisigAddress.getIndex() + " signingIndex: " + multisigAddress.getSigningIndex());
|
||||
|
||||
multisigs.add(multisigAddress);
|
||||
}
|
||||
|
||||
return multisigs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param user
|
||||
* @param multisigAddress
|
||||
* @return
|
||||
*/
|
||||
public static MultisigAddress updateMultisigChildrenForUser(UserObject user, MultisigAddress multisigAddress) {
|
||||
FlashObject flash = user.getFlash();
|
||||
MultisigAddress originAddress = flash.getRoot().find(multisigAddress.getAddress());
|
||||
if (originAddress != null) {
|
||||
|
||||
System.out.println("[INFO]: found address in user" + user.getUserIndex() + " data");
|
||||
originAddress.setChildren(multisigAddress.getChildren());
|
||||
originAddress.setBundles(multisigAddress.getBundles());
|
||||
originAddress.setSecurity(multisigAddress.getSecurity());
|
||||
return originAddress;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ public class IotaFlashBridge {
|
||||
* @param transfers array of all transfers (value, address) pairs
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<Transfer> prepare(ArrayList<String> settlementAddresses, ArrayList<Integer> deposits, int index, ArrayList<Transfer> transfers) {
|
||||
public static ArrayList<Transfer> prepare(ArrayList<String> settlementAddresses, ArrayList<Double> deposits, int index, ArrayList<Transfer> transfers) {
|
||||
|
||||
// Now put all params into JS ready array.
|
||||
List<Object> params = new ArrayList<>();
|
||||
@@ -145,7 +145,7 @@ public class IotaFlashBridge {
|
||||
* @param deposits
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<Transfer> close(ArrayList<String> settlementAddresses, ArrayList<Integer> deposits) {
|
||||
public static ArrayList<Transfer> close(ArrayList<String> settlementAddresses, ArrayList<Double> deposits) {
|
||||
V8Array saJS = V8ObjectUtils.toV8Array(engine, settlementAddresses);
|
||||
// Deposits
|
||||
V8Array depositsJS = V8ObjectUtils.toV8Array(engine, deposits);
|
||||
@@ -172,16 +172,13 @@ public class IotaFlashBridge {
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<Bundle> compose(int balance,
|
||||
List<Integer> deposits,
|
||||
List<Double> deposits,
|
||||
ArrayList<Bundle> outputs,
|
||||
MultisigAddress root,
|
||||
MultisigAddress remainderAddress,
|
||||
ArrayList<Bundle> history,
|
||||
ArrayList<Transfer> transfers,
|
||||
boolean close) {
|
||||
|
||||
|
||||
|
||||
// Create params.
|
||||
// Now put all params into JS ready array.
|
||||
List<Object> params = new ArrayList<Object>();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package iotaFlashWrapper;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.operations.Mult;
|
||||
import iotaFlashWrapper.Model.*;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -25,7 +26,7 @@ public class Main {
|
||||
// INITIAL CHANNEL CONDITIONS
|
||||
|
||||
// Security level
|
||||
int SECURITY = 2;
|
||||
int SECURITY = 1;
|
||||
// Number of parties taking signing part in the channel
|
||||
int SIGNERS_COUNT = 2;
|
||||
// Flash tree depth
|
||||
@@ -33,252 +34,189 @@ public class Main {
|
||||
// Total channel Balance
|
||||
int CHANNEL_BALANCE = 2000;
|
||||
// Users deposits
|
||||
ArrayList<Integer> DEPOSITS = new ArrayList<>();
|
||||
DEPOSITS.add(1000);
|
||||
DEPOSITS.add(1000);
|
||||
ArrayList<Double> DEPOSITS = new ArrayList<>();
|
||||
DEPOSITS.add(1000.0);
|
||||
DEPOSITS.add(1000.0);
|
||||
// Setup users.
|
||||
FlashObject oneFlashObj = new FlashObject(SIGNERS_COUNT, CHANNEL_BALANCE, DEPOSITS);
|
||||
UserObject oneFlash = new UserObject(0, oneSeed, TREE_DEPTH, oneFlashObj);
|
||||
UserObject oneFlash = new UserObject(0, oneSeed, TREE_DEPTH, SECURITY, oneFlashObj);
|
||||
|
||||
FlashObject twoFlashObj = new FlashObject(SIGNERS_COUNT, CHANNEL_BALANCE, DEPOSITS);
|
||||
UserObject twoFlash = new UserObject(1, twoSeed, TREE_DEPTH, twoFlashObj);
|
||||
UserObject twoFlash = new UserObject(1, twoSeed, TREE_DEPTH, SECURITY, twoFlashObj);
|
||||
|
||||
// USER ONE
|
||||
setupUser(oneFlash, TREE_DEPTH);
|
||||
ArrayList<Digest> oneDigests = Helpers.getDigestsForUser(oneFlash, TREE_DEPTH);
|
||||
|
||||
// USER TWO
|
||||
setupUser(twoFlash, TREE_DEPTH);
|
||||
ArrayList<Digest> twoDigests = Helpers.getDigestsForUser(twoFlash, TREE_DEPTH);
|
||||
|
||||
//////////////////////////////////
|
||||
// INITAL MULTISIG
|
||||
|
||||
// Make an array of digests
|
||||
ArrayList<UserObject> allUsers = new ArrayList<UserObject>();
|
||||
allUsers.add(oneFlash);
|
||||
allUsers.add(twoFlash);
|
||||
ArrayList<ArrayList<Digest>> allUserDigests = new ArrayList<>();
|
||||
allUserDigests.add(oneDigests);
|
||||
allUserDigests.add(twoDigests);
|
||||
|
||||
// Create partial digests for users.
|
||||
createInitialPartialDigests(allUsers, oneFlash);
|
||||
createInitialPartialDigests(allUsers, twoFlash);
|
||||
|
||||
ArrayList<MultisigAddress> oneMultisigs = oneFlash.getMultisigDigests();
|
||||
ArrayList<MultisigAddress> twoMultisigs = twoFlash.getMultisigDigests();
|
||||
|
||||
/***************************************
|
||||
User one setup.
|
||||
***************************************/
|
||||
|
||||
// Create multisigs.
|
||||
ArrayList<MultisigAddress> oneMultisigs = Helpers.getMultisigsForUser(allUserDigests, oneFlash);
|
||||
|
||||
// Set renainder address.
|
||||
MultisigAddress oneRemainderAddr = oneMultisigs.remove(0); //shiftCopyArray();
|
||||
oneFlash.getFlash().setRemainderAddress(oneRemainderAddr);
|
||||
|
||||
MultisigAddress twoRemainderAddr = twoMultisigs.remove(0);
|
||||
twoFlash.getFlash().setRemainderAddress(twoRemainderAddr);
|
||||
|
||||
// Build flash trees
|
||||
for (int i = 1; i < oneMultisigs.size(); i++) {
|
||||
System.out.println(oneMultisigs.get(i - 1).toString() + " -> " + oneMultisigs.get(i).toString());
|
||||
oneMultisigs.get(i - 1).push(oneMultisigs.get(i));
|
||||
}
|
||||
oneFlash.getFlash().setRoot(oneMultisigs.remove(0));
|
||||
|
||||
|
||||
|
||||
/***************************************
|
||||
User one setup.
|
||||
***************************************/
|
||||
|
||||
ArrayList<MultisigAddress> twoMultisigs = Helpers.getMultisigsForUser(allUserDigests, twoFlash);
|
||||
// Set user two remainder addr.
|
||||
MultisigAddress twoRemainderAddr = twoMultisigs.remove(0);
|
||||
twoFlash.getFlash().setRemainderAddress(twoRemainderAddr);
|
||||
|
||||
// Build flash trees
|
||||
for (int i = 1; i < twoMultisigs.size(); i++) {
|
||||
twoMultisigs.get(i - 1).push(twoMultisigs.get(i));
|
||||
}
|
||||
|
||||
oneFlash.getFlash().setRoot(oneMultisigs.remove(0));
|
||||
twoFlash.getFlash().setRoot(twoMultisigs.remove(0));
|
||||
|
||||
|
||||
|
||||
/***************************************
|
||||
Setup tettlements.
|
||||
***************************************/
|
||||
|
||||
ArrayList<String> settlementAddresses = new ArrayList<>();
|
||||
settlementAddresses.add(oneSettlement);
|
||||
settlementAddresses.add(twoSettlement);
|
||||
|
||||
|
||||
|
||||
/***************************************
|
||||
Setup tettlements.
|
||||
***************************************/
|
||||
|
||||
oneFlash.getFlash().setSettlementAddresses(settlementAddresses);
|
||||
twoFlash.getFlash().setSettlementAddresses(settlementAddresses);
|
||||
|
||||
// Set digest/key index
|
||||
oneFlash.setIndex(oneFlash.getPartialDigests().size());
|
||||
twoFlash.setIndex(twoFlash.getPartialDigests().size());
|
||||
oneFlash.setIndex(oneDigests.size());
|
||||
twoFlash.setIndex(twoDigests.size());
|
||||
|
||||
System.out.println("Channel Setup!");
|
||||
System.out.println("Channel Setup completed!");
|
||||
|
||||
ArrayList<Transfer> transfers = new ArrayList<>();
|
||||
transfers.add(new Transfer(twoSettlement, 1));
|
||||
transfers.add(new Transfer(twoSettlement, 400));
|
||||
|
||||
System.out.println(oneFlash);
|
||||
|
||||
System.out.println("Creating a transaction: 200 to " + twoSettlement);
|
||||
ArrayList<Bundle> bundles = Helpers.createTransaction(oneFlash, transfers, false);
|
||||
|
||||
ArrayList<Bundle> partialSignedBundles = signTransfer(bundles, oneFlash);
|
||||
ArrayList<Bundle> signedBundles = signTransfer(partialSignedBundles, twoFlash);
|
||||
/////////////////////////////////
|
||||
/// APPLY SIGNED BUNDLES
|
||||
|
||||
// Apply transfers to User ONE
|
||||
Helpers.applyTransfers(oneFlash, signedBundles);
|
||||
|
||||
// Save latest channel bundles
|
||||
oneFlash.setBundles(signedBundles);
|
||||
|
||||
// Apply transfers to User TWO
|
||||
Helpers.applyTransfers(twoFlash, signedBundles);
|
||||
// Save latest channel bundles
|
||||
twoFlash.setBundles(signedBundles);
|
||||
System.out.println("[SUCCESS] Apply Transfer to flash channel.");
|
||||
/***************************************
|
||||
Create transactions.
|
||||
***************************************/
|
||||
|
||||
|
||||
System.out.println("Transaction Applied!");
|
||||
// System.out.println(
|
||||
// "Transactable tokens: " +
|
||||
// oneFlash.getFlash().getDeposits().stream().mapToInt(v -> v.intValue()).sum()
|
||||
// );
|
||||
// Create transfer from user one
|
||||
ArrayList<Bundle> suggestedTransfer;
|
||||
|
||||
// Accept transfers from other user
|
||||
ArrayList<Bundle> confirmedTransfers;
|
||||
|
||||
// Try to make 10 transfers.
|
||||
for (int i = 0; i < 10; i++) {
|
||||
|
||||
// Create transaction helper and check if we need to add nodes
|
||||
CreateTransactionHelperObject helper = Helpers.getTransactionHelper(oneFlash.getFlash().getRoot());
|
||||
|
||||
// Check if we need to create new addresses. This must be done before a transaction is prepared.
|
||||
// The createTransaction will then create funding fundles for the new address.
|
||||
if (helper.getGenerate() != 0) {
|
||||
System.out.println("[WARN]: generating " + helper.getGenerate() + "new branches!");
|
||||
|
||||
// Add user one digests.
|
||||
ArrayList<Digest> newOneDigests = Helpers.getNewBranchDigests(oneFlash, helper.getGenerate());
|
||||
|
||||
// Add user two digests
|
||||
ArrayList<Digest> newTwoDigests = Helpers.getNewBranchDigests(twoFlash, helper.getGenerate());
|
||||
|
||||
// Now we can create new multisig addresses
|
||||
MultisigAddress multisigAddressOne = Helpers.getNewBranch(newOneDigests, newTwoDigests, oneFlash, helper.getAddress());
|
||||
MultisigAddress multisigAddressTwo = Helpers.getNewBranch(newOneDigests, newTwoDigests, twoFlash, helper.getAddress());
|
||||
|
||||
// Find the multisig with the address and append new address to children
|
||||
Helpers.updateMultisigChildrenForUser(oneFlash, multisigAddressOne);
|
||||
Helpers.updateMultisigChildrenForUser(twoFlash, multisigAddressTwo);
|
||||
|
||||
// Set the updated multisig as origin of the transaction.
|
||||
helper.setAddress(multisigAddressOne);
|
||||
}
|
||||
|
||||
// Create transfers.
|
||||
ArrayList<Transfer> transfers = new ArrayList<>();
|
||||
transfers.add(new Transfer(twoSettlement, 20));
|
||||
|
||||
// Create a transaction from a transfer.
|
||||
suggestedTransfer = Helpers.createTransaction(transfers, helper, oneFlash, false);
|
||||
|
||||
System.out.println("[INFO] Created transfer suggestion.");
|
||||
|
||||
// TODO: check here if transaction is valid.
|
||||
|
||||
// If transactions should be signed create signatures.
|
||||
ArrayList<Signature> userTwoSignatures = IotaFlashBridge.sign(twoFlash.getFlash().getRoot(), twoFlash.getSeed(), suggestedTransfer);
|
||||
System.out.println("[INFO] Created user two signatures.");
|
||||
// TODO: the signatures should be sind to the first user.
|
||||
|
||||
// Apply transfers by all users.
|
||||
System.out.println("[INFO] Signing transfers.");
|
||||
ArrayList<Bundle> signedBundlesOne = IotaFlashBridge.appliedSignatures(suggestedTransfer, userTwoSignatures);
|
||||
ArrayList<Bundle> signedBundlesTwo = IotaFlashBridge.appliedSignatures(suggestedTransfer, userTwoSignatures);
|
||||
applyTransfers(signedBundlesOne, oneFlash);
|
||||
applyTransfers(signedBundlesTwo, twoFlash);
|
||||
|
||||
System.out.println("Transaction Applied! Transactable tokens: " + getFlashDeposits(oneFlash));
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
public static void applyTransfers(ArrayList<Bundle> signedBundles, UserObject user) {
|
||||
// Apply transfers to User ONE
|
||||
oneFlash = Helpers.applyTransfers(oneFlash, signedBundles)
|
||||
FlashObject newFlash = IotaFlashBridge.applyTransfersToUser(user, signedBundles);
|
||||
|
||||
// Set new flash object to user
|
||||
user.setFlash(newFlash);
|
||||
|
||||
// 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: ")*/
|
||||
user.setBundles(signedBundles);
|
||||
}
|
||||
|
||||
private static ArrayList<Bundle> signTransfer(ArrayList<Bundle> bundles, UserObject user) {
|
||||
System.out.println("[SUCCESS] Created signatures for users.");
|
||||
ArrayList<Signature> oneSignatures = Helpers.signTransaction(user, bundles);
|
||||
|
||||
System.out.println("[SUCCESS] Parial applied Signature for User one on transfer bundle");
|
||||
// Sign bundle with your USER ONE'S signatures
|
||||
ArrayList<Bundle> signedBundles = IotaFlashBridge.appliedSignatures(bundles, oneSignatures);
|
||||
|
||||
return signedBundles;
|
||||
}
|
||||
|
||||
private static void setupUser(UserObject user, int TREE_DEPTH) {
|
||||
// Create digests for the start of the channel
|
||||
for (int i = 0; i < TREE_DEPTH + 1; i++) {
|
||||
// Create new digest
|
||||
Digest digest = IotaFlashBridge.getDigest(
|
||||
user.getSeed(),
|
||||
user.getIndex(),
|
||||
user.getSecurity()
|
||||
);
|
||||
System.out.println("Adding digest (" + digest.toString() + ") to user " + user.getUserIndex());
|
||||
// Increment key index
|
||||
user.incrementIndex();
|
||||
user.add(digest);
|
||||
public static double getFlashDeposits(UserObject user) {
|
||||
double sum = 0;
|
||||
for (double deposit : user.getFlash().getDeposits()) {
|
||||
sum += deposit;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private static void createInitialPartialDigests(ArrayList<UserObject> allUsers, UserObject currentUser) {
|
||||
|
||||
// Generate the first addresses
|
||||
ArrayList<MultisigAddress> oneMultisigs = new ArrayList<MultisigAddress>();
|
||||
|
||||
|
||||
System.out.println("_________________________________________________________________");
|
||||
System.out.println("Creating multisigs on user: " + currentUser.getUserIndex());
|
||||
int index = 0;
|
||||
// Create address
|
||||
for (Digest digest: allUsers.get(index).getPartialDigests()) {
|
||||
int i = index;
|
||||
|
||||
MultisigAddress addy = IotaFlashBridge.composeAddress(
|
||||
allUsers.stream().map(u -> u.getPartialDigests().get(i)).collect(Collectors.toCollection(ArrayList::new))
|
||||
);
|
||||
|
||||
System.out.println("Multisig: " + addy.toString());
|
||||
|
||||
// Add key index in
|
||||
addy.setIndex(digest.getIndex());
|
||||
// Add the signing index to the object IMPORTANT
|
||||
addy.setSigningIndex(currentUser.getUserIndex() * digest.getSecurity());
|
||||
// Get the sum of all digest security to get address security sum
|
||||
addy.setSecuritySum(allUsers.stream()
|
||||
.map(u -> u.getPartialDigests().get(i))
|
||||
.mapToInt(Digest::getSecurity)
|
||||
.sum()
|
||||
);
|
||||
addy.setSecurity(digest.getSecurity());
|
||||
oneMultisigs.add(addy);
|
||||
index++;
|
||||
}
|
||||
currentUser.setMultisigDigests(oneMultisigs);
|
||||
}
|
||||
|
||||
private static ArrayList<MultisigAddress> shiftCopyArray(ArrayList<MultisigAddress> input) {
|
||||
ArrayList<MultisigAddress> output = new ArrayList<>();
|
||||
|
||||
for (int i = 1; i < input.size(); i++) {
|
||||
output.add(input.get(i));
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private static void test() throws IOException {
|
||||
|
||||
System.out.println("IOTA Flash channel tester");
|
||||
|
||||
String pathToLib = "res/iota.flash.js";
|
||||
|
||||
System.out.println("Loading lib into V8 engine");
|
||||
System.out.println("Lib imported");
|
||||
|
||||
|
||||
System.out.println("Testing getDigest(seed, index, security):");
|
||||
Digest digest1 = IotaFlashBridge.getDigest("USERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSER", 0, 2);
|
||||
Digest digest2 = IotaFlashBridge.getDigest("USERTWOUSERTWOUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSER", 0, 2);
|
||||
System.out.println("Digest1: " + digest1.toString());
|
||||
|
||||
|
||||
System.out.println("Testing composeAddress(digests):");
|
||||
ArrayList<Digest> digests = new ArrayList<Digest>();
|
||||
digests.add(digest1);
|
||||
digests.add(digest2);
|
||||
MultisigAddress composedAddr = IotaFlashBridge.composeAddress(digests);
|
||||
System.out.println("Got multisig addr for digests: " + composedAddr.getAddress() + ", securitySum: " + composedAddr.getSecuritySum());
|
||||
|
||||
testPrepare();
|
||||
}
|
||||
|
||||
private static void testPrepare() {
|
||||
|
||||
System.out.println("Testing prepare()");
|
||||
ArrayList<String> settlementAddr = new ArrayList<String>();
|
||||
settlementAddr.add("RCZHCRDWMGJPHKROKEGVADVJXPGKEKNJRNLZZFPITUVEWNPGIWNUMKTYKMNB9DCNLWGMJZDNKYQDQKDLC");
|
||||
ArrayList<Integer> depositsPrep = new ArrayList<Integer>();
|
||||
ArrayList<Transfer> transfers = new ArrayList<Transfer>();
|
||||
|
||||
IotaFlashBridge.prepare(settlementAddr, depositsPrep, 0, transfers);
|
||||
/**
|
||||
* acceptTransfer applies signatures of a
|
||||
* @param bundles half signed transfers
|
||||
* @param signatures signatures of the second user
|
||||
*/
|
||||
public static void acceptTransfer(ArrayList<Bundle> bundles, ArrayList<Signature> signatures, UserObject user) {
|
||||
ArrayList<Bundle> signedBundles = IotaFlashBridge.appliedSignatures(bundles, signatures);
|
||||
applyTransfers(signedBundles, user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,12 +28,17 @@ public class Bundle {
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
|
||||
map.put("bundles", toArrayList());
|
||||
return map;
|
||||
}
|
||||
|
||||
public List<Object> toArrayList() {
|
||||
List<Object> bundleList = new ArrayList<Object>();
|
||||
for (Transaction b: bundles) {
|
||||
bundleList.add(b.toMap());
|
||||
}
|
||||
map.put("bundles", bundleList);
|
||||
return map;
|
||||
return bundleList;
|
||||
}
|
||||
|
||||
public ArrayList<Transaction> getBundles() {
|
||||
|
||||
@@ -16,4 +16,8 @@ public class CreateTransactionHelperObject {
|
||||
public MultisigAddress getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(MultisigAddress address) {
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
@@ -8,20 +8,20 @@ public class FlashObject {
|
||||
int signersCount = 2;
|
||||
int balance;
|
||||
ArrayList<String> settlementAddresses;
|
||||
ArrayList<Integer> deposits; // Clone correctly
|
||||
ArrayList<Double> deposits;
|
||||
ArrayList<Bundle> outputs = new ArrayList<Bundle>();
|
||||
ArrayList<Bundle> transfers = new ArrayList<Bundle>();
|
||||
MultisigAddress root;
|
||||
MultisigAddress remainderAddress;
|
||||
|
||||
|
||||
public FlashObject(int signersCount, int balance, ArrayList<Integer> deposits) {
|
||||
public FlashObject(int signersCount, int balance, ArrayList<Double> deposits) {
|
||||
this.signersCount = signersCount;
|
||||
this.balance = balance;
|
||||
this.deposits = deposits;
|
||||
}
|
||||
|
||||
public FlashObject(int signersCount, int balance, ArrayList<String> settlementAddresses, ArrayList<Integer> deposits, ArrayList<Bundle> outputs, ArrayList<Bundle> transfers, MultisigAddress root, MultisigAddress remainderAddress) {
|
||||
public FlashObject(int signersCount, int balance, ArrayList<String> settlementAddresses, ArrayList<Double> deposits, ArrayList<Bundle> outputs, ArrayList<Bundle> transfers, MultisigAddress root, MultisigAddress remainderAddress) {
|
||||
this.signersCount = signersCount;
|
||||
this.balance = balance;
|
||||
this.settlementAddresses = settlementAddresses;
|
||||
@@ -42,7 +42,7 @@ public class FlashObject {
|
||||
out += "\t" + b + "\n";
|
||||
}
|
||||
out += "deposits: " + "\n";
|
||||
for (Integer b: deposits) {
|
||||
for (double b: deposits) {
|
||||
out += "\t" + b + "\n";
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class FlashObject {
|
||||
return root;
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getDeposits() {
|
||||
public ArrayList<Double> getDeposits() {
|
||||
return deposits;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package iotaFlashWrapper.Model;
|
||||
import com.eclipsesource.v8.V8;
|
||||
import com.eclipsesource.v8.V8Object;
|
||||
import com.eclipsesource.v8.utils.V8ObjectUtils;
|
||||
import com.sun.org.apache.xpath.internal.operations.Mult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -24,7 +25,6 @@ public class MultisigAddress {
|
||||
this.securitySum = securitySum;
|
||||
this.children = new ArrayList<MultisigAddress>();
|
||||
this.bundles = new ArrayList<Bundle>();
|
||||
|
||||
}
|
||||
|
||||
public MultisigAddress(String address, int securitySum, ArrayList<MultisigAddress> children) {
|
||||
@@ -34,6 +34,42 @@ public class MultisigAddress {
|
||||
this.bundles = new ArrayList<Bundle>();
|
||||
}
|
||||
|
||||
public MultisigAddress find(String address) {
|
||||
if (getAddress().equals(address)) {
|
||||
return this;
|
||||
} else {
|
||||
for (MultisigAddress mult: getChildren()) {
|
||||
MultisigAddress result = mult.find(address);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public MultisigAddress clone() {
|
||||
MultisigAddress output = new MultisigAddress(this.getAddress(), this.getSecuritySum());
|
||||
|
||||
output.setSecurity(this.getSecurity());
|
||||
output.setIndex(this.getIndex());
|
||||
output.setSigningIndex(this.getSigningIndex());
|
||||
// Copy all bundles
|
||||
ArrayList<Bundle> bundleCopy = new ArrayList<>();
|
||||
for (Bundle b : this.getBundles()) {
|
||||
bundleCopy.add(b.clone());
|
||||
}
|
||||
output.setBundles(bundleCopy);
|
||||
|
||||
// Copy all children
|
||||
ArrayList<MultisigAddress> childrenCopy = new ArrayList<>();
|
||||
for (MultisigAddress child : this.getChildren()) {
|
||||
childrenCopy.add(child.clone());
|
||||
}
|
||||
output.setChildren(childrenCopy);
|
||||
return output;
|
||||
}
|
||||
|
||||
public void push(MultisigAddress addr) {
|
||||
children.add(addr);
|
||||
}
|
||||
@@ -53,6 +89,22 @@ public class MultisigAddress {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public void setChildren(ArrayList<MultisigAddress> children) {
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
public ArrayList<Bundle> getBundles() {
|
||||
return bundles;
|
||||
}
|
||||
|
||||
public void setBundles(ArrayList<Bundle> bundles) {
|
||||
this.bundles = bundles;
|
||||
}
|
||||
|
||||
public int getSigningIndex() {
|
||||
return signingIndex;
|
||||
}
|
||||
@@ -92,7 +144,7 @@ public class MultisigAddress {
|
||||
|
||||
List<Object> bundleList = new ArrayList<Object>();
|
||||
for (Bundle b: bundles) {
|
||||
bundleList.add(b.getBundles());
|
||||
bundleList.add(b.toArrayList());
|
||||
}
|
||||
map.put("bundles", bundleList);
|
||||
|
||||
|
||||
@@ -5,25 +5,27 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class UserObject {
|
||||
private int userIndex = 1;
|
||||
private int userIndex;
|
||||
private String seed;
|
||||
private int index = 0;
|
||||
private int security = 2;
|
||||
private int depth = 4;
|
||||
private int security;
|
||||
private int depth;
|
||||
private ArrayList<Bundle> bundles = new ArrayList<Bundle>();
|
||||
private ArrayList<Digest> partialDigests = new ArrayList<Digest>();
|
||||
private ArrayList<MultisigAddress> multisigDigests = new ArrayList<MultisigAddress>();
|
||||
private FlashObject flash;
|
||||
|
||||
public UserObject(int userID, String seed, int depth, FlashObject flash) {
|
||||
public UserObject(int userID, String seed, int depth, int security, FlashObject flash) {
|
||||
this.userIndex = userID;
|
||||
this.seed = seed;
|
||||
this.depth = depth;
|
||||
this.security = security;
|
||||
this.flash = flash;
|
||||
}
|
||||
|
||||
public void incrementIndex() {
|
||||
index++;
|
||||
public int incrementIndex() {
|
||||
this.index = this.index + 1;
|
||||
return index;
|
||||
}
|
||||
|
||||
public void add(Digest digest) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package iotaFlashWrapper;
|
||||
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 iotaFlashWrapper.Model.*;
|
||||
|
||||
@@ -52,7 +53,17 @@ public class V8Converter {
|
||||
ArrayList<String> settlementAddresses = (ArrayList<String>) inputMap.get("settlementAddresses");
|
||||
MultisigAddress root = multisigAddressFromPropertyMap((Map<String, Object>) inputMap.get("root"));
|
||||
MultisigAddress remainderAddress = multisigAddressFromPropertyMap((Map<String, Object>) inputMap.get("remainderAddress"));
|
||||
ArrayList<Integer> deposits = (ArrayList<Integer>) inputMap.get("deposits");
|
||||
ArrayList<Double> deposits = new ArrayList<>();
|
||||
if (inputMap.get("deposits") instanceof ArrayList) {
|
||||
Object depositEntry = inputMap.get("deposits");
|
||||
if (((ArrayList<Object>) depositEntry).size() > 0 && ((ArrayList<Object>) depositEntry).get(0) instanceof Integer) {
|
||||
for (int val: (ArrayList<Integer>) depositEntry) {
|
||||
deposits.add(new Double(val));
|
||||
}
|
||||
} else {
|
||||
deposits = (ArrayList<Double>) depositEntry;
|
||||
}
|
||||
}
|
||||
ArrayList<Bundle> transfers = bundleListFromArrayList((ArrayList<Object>) inputMap.get("transfers"));
|
||||
ArrayList<Bundle> outputs = bundleListFromArrayList((ArrayList<Object>) inputMap.get("outputs"));
|
||||
|
||||
@@ -84,7 +95,17 @@ public class V8Converter {
|
||||
ArrayList<Bundle> ret = new ArrayList<>();
|
||||
|
||||
for (Object o: input) {
|
||||
ret.add(bundleFromArrayList((ArrayList<Object>) o));
|
||||
if (o instanceof Map) {
|
||||
if (((Map) o).get("bundles") instanceof String) {
|
||||
ArrayList<Object> bundles = (ArrayList<Object>) ((Map<String, Object>) o).get("bundles");
|
||||
ret.add(bundleFromArrayList(bundles));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (o instanceof ArrayList) {
|
||||
ret.add(bundleFromArrayList((ArrayList<Object>) o));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +113,10 @@ public class V8Converter {
|
||||
}
|
||||
|
||||
public static MultisigAddress multisigAddressFromV8Object(V8Object input) {
|
||||
if (input.isUndefined()) {
|
||||
System.out.println("[ERROR]: could not parse object");
|
||||
return null;
|
||||
}
|
||||
Map<String, ? super Object> multiSigMap = V8ObjectUtils.toMap(input);
|
||||
return multisigAddressFromPropertyMap(multiSigMap);
|
||||
}
|
||||
@@ -101,7 +126,6 @@ public class V8Converter {
|
||||
String addr = (String) propMap.get("address");
|
||||
int secSum = (Integer) propMap.get("securitySum");
|
||||
|
||||
|
||||
ArrayList<MultisigAddress> children = new ArrayList<>();
|
||||
|
||||
for (Object child: (ArrayList<Object>) propMap.get("children")) {
|
||||
@@ -111,6 +135,23 @@ public class V8Converter {
|
||||
|
||||
MultisigAddress multisig = new MultisigAddress(addr, secSum, children);
|
||||
|
||||
if (propMap.get("bundles") instanceof ArrayList) {
|
||||
ArrayList<Bundle> bundles = new ArrayList<>();
|
||||
for (Object bundle: (ArrayList<Object>) propMap.get("bundles")) {
|
||||
Bundle b = new Bundle();
|
||||
if (!(bundle instanceof ArrayList)) {
|
||||
continue;
|
||||
} else {
|
||||
for (Object transactionMap: (ArrayList<Object>) bundle) {
|
||||
b.getBundles().add(transactionFromObject(transactionMap));
|
||||
}
|
||||
}
|
||||
bundles.add(b);
|
||||
}
|
||||
|
||||
multisig.setBundles(bundles);
|
||||
}
|
||||
|
||||
if (propMap.get("index") != null) {
|
||||
multisig.setIndex((Integer) propMap.get("index"));
|
||||
}
|
||||
@@ -118,6 +159,10 @@ public class V8Converter {
|
||||
multisig.setSigningIndex((Integer) propMap.get("signingIndex"));
|
||||
}
|
||||
|
||||
if (propMap.get("security") instanceof Integer) {
|
||||
multisig.setSecurity((Integer) propMap.get("security"));
|
||||
}
|
||||
|
||||
return multisig;
|
||||
}
|
||||
|
||||
@@ -126,6 +171,10 @@ public class V8Converter {
|
||||
// Parse return as array of bundles
|
||||
ArrayList<Bundle> returnBundles = new ArrayList<>();
|
||||
for (Object bundleItem: inputList) {
|
||||
if (!(bundleItem instanceof ArrayList)) {
|
||||
System.out.println("[ERROR]: got undefined for bunle");
|
||||
continue;
|
||||
}
|
||||
ArrayList<Object> bundleContent = (ArrayList<Object>) bundleItem;
|
||||
|
||||
ArrayList<Transaction> returnedTransactions = new ArrayList<>();
|
||||
|
||||
Reference in New Issue
Block a user