diff --git a/README.md b/README.md index aab45c5..f198ec6 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ The JOTA library is a simple Java wrapper around [[IOTA]](http://www.iotatoken.c It allows to connect easily using java directly to a local or a remote [[IOTA node]](https://iota.readme.io/docs/syncing-to-the-network). -* **Latest release:** 0.9.0 RC1 -* **Compatibility:** fully compatible with IOTA IRI v1.2.4 +* **Latest release:** 0.9.1 +* **Compatibility:** fully compatible with IOTA IRI v1.2.6 * **API coverage:** 14 of 14 commands fully implemented * **License:** Apache License 2.0 * **Readme updated:** 2016-01-19 21:05:02 (UTC) @@ -54,7 +54,7 @@ In order to communicate with *IOTA node*, JOTA needs to be aware of your node's iota.node.host=127.0.0.1 iota.node.port=14265 -Jota is still *not* in the central maven repository. It will be available when it will cover 100% iota's rest interface. +Jota is still *not* in the central maven repository. ##Warning - This is pre-release software! diff --git a/pom.xml b/pom.xml index becaf24..1a59524 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.iota jota - 0.9.0-RC1 + 0.9.1 JOTA JOTA library is a simple Java wrapper around IOTA Node's JSON-REST HTTP interface. diff --git a/src/main/java/jota/IotaAPI.java b/src/main/java/jota/IotaAPI.java index 6bac087..c6504bc 100644 --- a/src/main/java/jota/IotaAPI.java +++ b/src/main/java/jota/IotaAPI.java @@ -14,13 +14,13 @@ import java.util.*; /** * IotaAPI Builder. Usage: - * + *

* IotaApiProxy api = IotaApiProxy.Builder * .protocol("http") * .nodeAddress("localhost") * .port(12345) * .build(); - * + *

* GetNodeInfoResponse response = api.getNodeInfo(); * * @author davassi @@ -39,14 +39,14 @@ public class IotaAPI extends IotaAPICore { * Generates a new address from a seed and returns the remainderAddress. * This is either done deterministically, or by providing the index of the new remainderAddress. * - * @param seed Tryte-encoded seed. It should be noted that this seed is not transferred. - * @param security Security level to be used for the private key / address. Can be 1, 2 or 3. - * @param index Key index to start search from. If the index is provided, the generation of the address is not deterministic. - * @param checksum Adds 9-tryte address checksum. - * @param total Total number of addresses to generate. + * @param seed Tryte-encoded seed. It should be noted that this seed is not transferred. + * @param security Security level to be used for the private key / address. Can be 1, 2 or 3. + * @param index Key index to start search from. If the index is provided, the generation of the address is not deterministic. + * @param checksum Adds 9-tryte address checksum. + * @param total Total number of addresses to generate. * @param returnAll If true, it returns all addresses which were deterministically generated (until findTransactions returns null). * @return An array of strings with the specifed number of addresses. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws InvalidAddressException is thrown when the specified address is not an valid address. * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. */ public GetNewAddressResponse getNewAddress(final String seed, int security, final int index, final boolean checksum, final int total, final boolean returnAll) throws InvalidSecurityLevelException, InvalidAddressException { @@ -90,18 +90,18 @@ public class IotaAPI extends IotaAPICore { } /** - * @param seed Tryte-encoded seed. It should be noted that this seed is not transferred. - * @param security The security level of private key / seed. - * @param start Starting key index. - * @param end Ending key index. + * @param seed Tryte-encoded seed. It should be noted that this seed is not transferred. + * @param security The security level of private key / seed. + * @param start Starting key index. + * @param end Ending key index. * @param inclusionStates If true, it gets the inclusion states of the transfers. * @return Bundle of transfers. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. - * @throws ArgumentException is thrown when an invalid argument is provided. - * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. - * @throws InvalidSignatureException is thrown when an invalid signature is encountered. - * @throws NoNodeInfoException is thrown when its not possible to get node info. - * @throws NoInclusionStatesException when it not possible to get a inclusion state. + * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws ArgumentException is thrown when an invalid argument is provided. + * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. + * @throws InvalidSignatureException is thrown when an invalid signature is encountered. + * @throws NoNodeInfoException is thrown when its not possible to get node info. + * @throws NoInclusionStatesException when it not possible to get a inclusion state. * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. */ public GetTransferResponse getTransfers(String seed, int security, Integer start, Integer end, Boolean inclusionStates) throws ArgumentException, InvalidBundleException, InvalidSignatureException, NoNodeInfoException, NoInclusionStatesException, InvalidSecurityLevelException, InvalidAddressException { @@ -131,15 +131,15 @@ public class IotaAPI extends IotaAPICore { } /** - * * Internal function to get the formatted bundles of a list of addresses. - * @param addresses List of addresses. + * + * @param addresses List of addresses. * @param inclusionStates If true, it gets the inclusion states of the transfers. * @return A Transaction objects. - * @throws ArgumentException is thrown when an invalid argument is provided. - * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. - * @throws InvalidSignatureException is thrown when an invalid signature is encountered. - * @throws NoNodeInfoException is thrown when its not possible to get node info. + * @throws ArgumentException is thrown when an invalid argument is provided. + * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. + * @throws InvalidSignatureException is thrown when an invalid signature is encountered. + * @throws NoNodeInfoException is thrown when its not possible to get node info. * @throws NoInclusionStatesException when it not possible to get a inclusion state. */ public Bundle[] bundlesFromAddresses(String[] addresses, final Boolean inclusionStates) throws ArgumentException, InvalidBundleException, InvalidSignatureException, NoNodeInfoException, NoInclusionStatesException { @@ -242,8 +242,8 @@ public class IotaAPI extends IotaAPICore { /** * Facade method: Gets transactions to approve, attaches to Tangle, broadcasts and stores. * - * @param trytes The trytes. - * @param depth The depth. + * @param trytes The trytes. + * @param depth The depth. * @param minWeightMagnitude The minimum weight magnitude. * @return Transactions objects. * @throws InvalidTrytesException is thrown when invalid trytes is provided. @@ -326,16 +326,16 @@ public class IotaAPI extends IotaAPICore { /** * Prepares transfer by generating bundle, finding and signing inputs. * - * @param seed 81-tryte encoded address of recipient. - * @param security The security level of private key / seed. + * @param seed 81-tryte encoded address of recipient. + * @param security The security level of private key / seed. * @param transfers Array of transfer objects. * @param remainder If defined, this address will be used for sending the remainder value (of the inputs) to. - * @param inputs The inputs. + * @param inputs The inputs. * @return Returns bundle trytes. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. - * @throws NotEnoughBalanceException is thrown when a transfer fails because their is not enough balance to perform the transfer. + * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws NotEnoughBalanceException is thrown when a transfer fails because their is not enough balance to perform the transfer. * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. - * @throws InvalidTransferException is thrown when an invalid transfer is provided. + * @throws InvalidTransferException is thrown when an invalid transfer is provided. */ public List prepareTransfers(String seed, int security, final List transfers, String remainder, List inputs) throws NotEnoughBalanceException, InvalidSecurityLevelException, InvalidAddressException, InvalidTransferException { @@ -489,14 +489,13 @@ public class IotaAPI extends IotaAPICore { /** * Gets the inputs of a seed * - * @param seed Tryte-encoded seed. It should be noted that this seed is not transferred. - * @param security The Security level of private key / seed. - * @param start Starting key index. - * @param end Ending key index. + * @param seed Tryte-encoded seed. It should be noted that this seed is not transferred. + * @param security The Security level of private key / seed. + * @param start Starting key index. + * @param end Ending key index. * @param threshold Min balance required. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws InvalidAddressException is thrown when the specified address is not an valid address. * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. - **/ public GetBalancesAndFormatResponse getInputs(String seed, int security, int start, int end, long threshold) throws InvalidSecurityLevelException, InvalidAddressException { StopWatch stopWatch = new StopWatch(); @@ -552,10 +551,10 @@ public class IotaAPI extends IotaAPICore { * * @param addresses The addresses. * @param threshold Min balance required. - * @param start Starting key index. - * @param end Ending key index. + * @param start Starting key index. + * @param end Ending key index. * @param stopWatch the stopwatch. - * @param security The security level of private key / seed. + * @param security The security level of private key / seed. * @return Inputs object. * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. **/ @@ -606,8 +605,8 @@ public class IotaAPI extends IotaAPICore { * * @param transaction The transaction encoded in trytes. * @return an array of bundle, if there are multiple arrays it means that there are conflicting bundles. - * @throws ArgumentException is thrown when an invalid argument is provided. - * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. + * @throws ArgumentException is thrown when an invalid argument is provided. + * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. * @throws InvalidSignatureException is thrown when an invalid signature is encountered. */ public GetBundleResponse getBundle(String transaction) throws ArgumentException, InvalidBundleException, InvalidSignatureException { @@ -677,7 +676,7 @@ public class IotaAPI extends IotaAPICore { for (Signature aSignaturesToValidate : signaturesToValidate) { String[] signatureFragments = aSignaturesToValidate.getSignatureFragments().toArray(new String[aSignaturesToValidate.getSignatureFragments().size()]); String address = aSignaturesToValidate.getAddress(); - boolean isValidSignature = new Signing().validateSignatures(address, signatureFragments, bundleHash); + boolean isValidSignature = new Signing(customCurl.clone()).validateSignatures(address, signatureFragments, bundleHash); if (!isValidSignature) throw new InvalidSignatureException(); } @@ -688,14 +687,14 @@ public class IotaAPI extends IotaAPICore { /** * Replays a transfer by doing Proof of Work again. * - * @param transaction The transaction. - * @param depth The depth. + * @param transaction The transaction. + * @param depth The depth. * @param minWeightMagnitude The minimum weight magnitude. * @return Analyzed Transaction objects. - * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. - * @throws ArgumentException is thrown when an invalid argument is provided. + * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. + * @throws ArgumentException is thrown when an invalid argument is provided. * @throws InvalidSignatureException is thrown when an invalid signature is encountered. - * @throws InvalidTransferException is thrown when an invalid transfer is provided. + * @throws InvalidTransferException is thrown when an invalid transfer is provided. */ public ReplayBundleResponse replayBundle(String transaction, int depth, int minWeightMagnitude) throws InvalidBundleException, ArgumentException, InvalidSignatureException, InvalidTrytesException { StopWatch stopWatch = new StopWatch(); @@ -743,20 +742,20 @@ public class IotaAPI extends IotaAPICore { /** * Wrapper function that basically does prepareTransfers, as well as attachToTangle and finally, it broadcasts and stores the transactions locally. * - * @param seed Tryte-encoded seed - * @param security The security level of private key / seed. - * @param depth The depth. + * @param seed Tryte-encoded seed + * @param security The security level of private key / seed. + * @param depth The depth. * @param minWeightMagnitude The minimum weight magnitude. - * @param transfers Array of transfer objects. - * @param inputs List of inputs used for funding the transfer. - * @param address If defined, this address will be used for sending the remainder value (of the inputs) to. + * @param transfers Array of transfer objects. + * @param inputs List of inputs used for funding the transfer. + * @param address If defined, this address will be used for sending the remainder value (of the inputs) to. * @return Array of Transaction objects. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. - * @throws NotEnoughBalanceException is thrown when a transfer fails because their is not enough balance to perform the transfer. + * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws NotEnoughBalanceException is thrown when a transfer fails because their is not enough balance to perform the transfer. * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. - * @throws InvalidTrytesException is thrown when invalid trytes is provided. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. - * @throws InvalidTransferException is thrown when an invalid transfer is provided. + * @throws InvalidTrytesException is thrown when invalid trytes is provided. + * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws InvalidTransferException is thrown when an invalid transfer is provided. */ public SendTransferResponse sendTransfer(String seed, int security, int depth, int minWeightMagnitude, final List transfers, Input[] inputs, String address) throws NotEnoughBalanceException, InvalidSecurityLevelException, InvalidTrytesException, InvalidAddressException, InvalidTransferException { @@ -786,9 +785,9 @@ public class IotaAPI extends IotaAPICore { * the bundle hash of the transaction is no longer the same. In case the input * transaction hash is not a tail, we return an error. * - * @param trunkTx Hash of a trunk or a tail transaction of a bundle. + * @param trunkTx Hash of a trunk or a tail transaction of a bundle. * @param bundleHash The bundle hashes. - * @param bundle List of bundles to be populated. + * @param bundle List of bundles to be populated. * @return Transaction objects. * @throws ArgumentException is thrown when an invalid argument is provided. */ @@ -838,14 +837,15 @@ public class IotaAPI extends IotaAPICore { * Prepares transfer by generating the bundle with the corresponding cosigner transactions. * Does not contain signatures. * - * @param securitySum The sum of security levels used by all co-signers. - * @param inputAddress Array of input addresses as well as the securitySum. + * @param securitySum The sum of security levels used by all co-signers. + * @param inputAddress Array of input addresses as well as the securitySum. * @param remainderAddress Has to be generated by the cosigners before initiating the transfer, can be null if fully spent. * @return Bundle of transaction objects. - * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. + * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. * @throws InvalidAddressException is thrown when the specified address is not an valid address. */ - private GetTransferResponse initiateTransfer(int securitySum, final List inputAddress, String remainderAddress, final List transfers) throws InvalidAddressException, InvalidBundleException, InvalidTransferException { + public List initiateTransfer(int securitySum, final String inputAddress, String remainderAddress, + final List transfers, boolean testMode) throws InvalidAddressException, InvalidBundleException, InvalidTransferException { StopWatch sw = new StopWatch(); @@ -869,10 +869,8 @@ public class IotaAPI extends IotaAPICore { // validate input address - for (String address : inputAddress) { - if (!InputValidator.isAddress(address)) - throw new InvalidBundleException(); - } + if (!InputValidator.isAddress(inputAddress)) + throw new InvalidAddressException(); // validate remainder address if (remainderAddress != null && !InputValidator.isAddress(remainderAddress)) { @@ -944,7 +942,7 @@ public class IotaAPI extends IotaAPICore { // Get inputs if we are sending tokens if (totalValue != 0) { - GetBalancesResponse balancesResponse = getBalances(100, inputAddress); + GetBalancesResponse balancesResponse = getBalances(100, new String[]{inputAddress}); String[] balances = balancesResponse.getBalances(); long totalBalance = 0; @@ -958,16 +956,18 @@ public class IotaAPI extends IotaAPICore { // get current timestamp in seconds long timestamp = (long) Math.floor(Calendar.getInstance().getTimeInMillis() / 1000); + // bypass the balance checks during unit testing + if (testMode) + totalBalance += 1000; + if (totalBalance > 0) { long toSubtract = 0 - totalBalance; // Add input as bundle entry // Only a single entry, signatures will be added later - // TODO: unfinished stuff - bundle.addEntry(securitySum, "", toSubtract, tag, timestamp); + bundle.addEntry(securitySum, inputAddress, toSubtract, tag, timestamp); } - // Return not enough balance error if (totalValue > totalBalance) { throw new IllegalStateException("Not enough balance"); @@ -986,24 +986,12 @@ public class IotaAPI extends IotaAPICore { bundle.addEntry(1, remainderAddress, remainder, tag, timestamp); } - // TODO: unfinished stuff - /* + bundle.finalize(customCurl.clone()); bundle.addTrytes(signatureFragments); - List trxb = bundle.getTransactions(); - List bundleTrytes = new ArrayList<>(); - - for (Transaction trx : trxb) { - bundleTrytes.add(trx.toTrytes()); - } - - return GetTransferResponse.create(bundle.getTransactions(), sw.getElapsedTimeMili()); - */ - return null; - + return bundle.getTransactions(); } else { - throw new RuntimeException("Invalid value transfer: the transfer does not require a signature."); } @@ -1032,18 +1020,17 @@ public class IotaAPI extends IotaAPICore { } /** - * @param seed Tryte-encoded seed. - * @param security The security level of private key / seed. - * @param inputs List of inputs used for funding the transfer. - * @param bundle To be populated. - * @param tag The tag. - * @param totalValue The total value. - * @param remainderAddress If defined, this address will be used for sending the remainder value (of the inputs) to. + * @param seed Tryte-encoded seed. + * @param security The security level of private key / seed. + * @param inputs List of inputs used for funding the transfer. + * @param bundle To be populated. + * @param tag The tag. + * @param totalValue The total value. + * @param remainderAddress If defined, this address will be used for sending the remainder value (of the inputs) to. * @param signatureFragments The signature fragments. - * - * @throws NotEnoughBalanceException is thrown when a transfer fails because their is not enough balance to perform the transfer. + * @throws NotEnoughBalanceException is thrown when a transfer fails because their is not enough balance to perform the transfer. * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws InvalidAddressException is thrown when the specified address is not an valid address. */ public List addRemainder(final String seed, final int security, diff --git a/src/main/java/jota/IotaAPICommands.java b/src/main/java/jota/IotaAPICommands.java index 3995251..fe66f1b 100644 --- a/src/main/java/jota/IotaAPICommands.java +++ b/src/main/java/jota/IotaAPICommands.java @@ -2,7 +2,7 @@ package jota; /** * IOTA's node command list - * + *

* 'params' is not currently used. */ public enum IotaAPICommands { @@ -42,7 +42,6 @@ public enum IotaAPICommands { } /** - * * @return */ public int params() { diff --git a/src/main/java/jota/IotaAPICore.java b/src/main/java/jota/IotaAPICore.java index 9a54fc9..9eba60c 100644 --- a/src/main/java/jota/IotaAPICore.java +++ b/src/main/java/jota/IotaAPICore.java @@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit; /** * This class provides access to the Iota core API + * * @author Adrian */ public class IotaAPICore { @@ -65,7 +66,6 @@ public class IotaAPICore { } /** - * * @param env * @param def * @return @@ -188,7 +188,7 @@ public class IotaAPICore { } public GetAttachToTangleResponse attachToTangle(String trunkTransaction, String branchTransaction, Integer minWeightMagnitude, String... trytes) throws InvalidTrytesException { - if(!InputValidator.isArrayOfTrytes(trytes)){ + if (!InputValidator.isArrayOfTrytes(trytes)) { throw new InvalidTrytesException(); } @@ -268,7 +268,6 @@ public class IotaAPICore { } /** - * * @param host * @return */ @@ -278,7 +277,6 @@ public class IotaAPICore { } /** - * * @param port * @return */ @@ -288,7 +286,6 @@ public class IotaAPICore { } /** - * * @param protocol * @return */ diff --git a/src/main/java/jota/IotaAPIService.java b/src/main/java/jota/IotaAPIService.java index a626209..2946307 100644 --- a/src/main/java/jota/IotaAPIService.java +++ b/src/main/java/jota/IotaAPIService.java @@ -19,7 +19,7 @@ public interface IotaAPIService { /** * Returns information about your node. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "getNodeInfo"}' * @@ -31,7 +31,7 @@ public interface IotaAPIService { /** * Get the list of latest tips (unconfirmed transactions). - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "getNeighbors"}' */ @@ -41,7 +41,7 @@ public interface IotaAPIService { /** * Add a list of neighbors to your node. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "addNeighbors", "uris": ["udp://8.8.8.8:14265", "udp://8.8.8.5:14265"]}' */ @@ -51,7 +51,7 @@ public interface IotaAPIService { /** * Removes a list of neighbors to your node. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "removeNeighbors", "uris": ["udp://8.8.8.8:14265", "udp://8.8.8.5:14265"]}' */ @@ -61,7 +61,7 @@ public interface IotaAPIService { /** * Get the list of latest tips (unconfirmed transactions). - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "getTips"}' */ @@ -71,7 +71,7 @@ public interface IotaAPIService { /** * Find the transactions which match the specified input and return - * + *

* curl http://localhost:14265 \ -X POST \ -H 'Content-Type: application/json' \ * -d '{"command": "findTransactions", "addresses": ["RVORZ9SIIP9RCYMREUIXXVPQIPHVCNPQ9HZWYKFWYWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVAZETAIRPTM"]}' */ @@ -82,7 +82,7 @@ public interface IotaAPIService { /** * Get the inclusion states of a set of transactions. This is for determining if a transaction was accepted and confirmed by the network or not. You can search for multiple tips (and thus, milestones) to get past inclusion states of transactions. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "getInclusionStates", "transactions"Q9HZWYKFWYWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVAZETAIRPTM"], "tips" : []}' */ @@ -92,7 +92,7 @@ public interface IotaAPIService { /** * Returns the raw trytes data of a transaction. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "getTrytes", "hashes": ["OAATQS9VQLSXCLDJVJJVYUGONXAXOFMJOZNSYWRZSWECMXAQQURHQBJNLD9IOFEPGZEPEMPXCIVRX9999"]}' */ @@ -102,7 +102,7 @@ public interface IotaAPIService { /** * Tip selection which returns trunkTransaction and branchTransaction. The input value is the latest coordinator milestone, as provided through the getNodeInfo API call. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "getTransactionsToApprove", "depth": 27}' */ @@ -112,7 +112,7 @@ public interface IotaAPIService { /** * It returns the confirmed balance which a list of addresses have at the latest confirmed milestone. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "getBalances", "addresses": ["HBBYKAKTILIPVUKFOTSLHGENPTXYBNKXZFQFR9VQFWNBMTQNRVOUKPVPRNBSZVVILMAFBKOTBLGLWLOHQ"], "threshold": 100}' */ @@ -122,7 +122,7 @@ public interface IotaAPIService { /** * Attaches the specified transactions (trytes) to the Tangle by doing Proof of Work. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "attachToTangle", "trunkTransaction": "JVMTDGDPDFYHMZPMWEKKANBQSLSDTIIHAYQUMZOKHXXXGJHJDQPOMDOMNRDKYCZRUFZROZDADTHZC9999", "branchTransaction": "P9KFSJVGSPLXAEBJSHWFZLGP9GGJTIO9YITDEHATDTGAFLPLBZ9FOFWWTKMAZXZHFGQHUOXLXUALY9999", "minWeightMagnitude": 18, "trytes": ["TRYTVALUEHERE"]}' */ @@ -132,7 +132,7 @@ public interface IotaAPIService { /** * Interrupts and completely aborts the attachToTangle process. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "interruptAttachingToTangle" } */ @@ -142,7 +142,7 @@ public interface IotaAPIService { /** * Broadcast a list of transactions to all neighbors. The input trytes for this call are provided by attachToTangle. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "broadcastTransactions", "trytes": ["BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999"]} */ @@ -152,7 +152,7 @@ public interface IotaAPIService { /** * Store transactions into the local storage. The trytes to be used for this call are returned by attachToTangle. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "storeTransactions", "trytes": ["BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999"]}' */ diff --git a/src/main/java/jota/dto/response/GetBalancesResponse.java b/src/main/java/jota/dto/response/GetBalancesResponse.java index c06bf50..b295bde 100644 --- a/src/main/java/jota/dto/response/GetBalancesResponse.java +++ b/src/main/java/jota/dto/response/GetBalancesResponse.java @@ -29,6 +29,7 @@ public class GetBalancesResponse extends AbstractResponse { /** * Gets the balances. + * * @return The balances. */ public String[] getBalances() { diff --git a/src/main/java/jota/error/InvalidTrytesException.java b/src/main/java/jota/error/InvalidTrytesException.java index 7b56b12..de97ff0 100644 --- a/src/main/java/jota/error/InvalidTrytesException.java +++ b/src/main/java/jota/error/InvalidTrytesException.java @@ -2,6 +2,7 @@ package jota.error; /** * This exception occurs when invalid trytes is provided. + * * @author Adrian */ public class InvalidTrytesException extends BaseException { diff --git a/src/main/java/jota/error/NoNodeInfoException.java b/src/main/java/jota/error/NoNodeInfoException.java index fc18040..fba5f37 100644 --- a/src/main/java/jota/error/NoNodeInfoException.java +++ b/src/main/java/jota/error/NoNodeInfoException.java @@ -2,6 +2,7 @@ package jota.error; /** * This exception occurs when its not possible to get node info. + * * @author Adrian */ public class NoNodeInfoException extends BaseException { diff --git a/src/main/java/jota/model/Bundle.java b/src/main/java/jota/model/Bundle.java index 9f270c1..1de54f6 100644 --- a/src/main/java/jota/model/Bundle.java +++ b/src/main/java/jota/model/Bundle.java @@ -67,10 +67,10 @@ public class Bundle implements Comparable { * Adds a bundle entry. * * @param signatureMessageLength Length of the signature message. - * @param address The address. - * @param value The value. - * @param tag The tag. - * @param timestamp The timestamp. + * @param address The address. + * @param value The value. + * @param tag The tag. + * @param timestamp The timestamp. */ public void addEntry(int signatureMessageLength, String address, long value, String tag, long timestamp) { if (getTransactions() == null) { @@ -79,7 +79,7 @@ public class Bundle implements Comparable { for (int i = 0; i < signatureMessageLength; i++) { Transaction trx = new Transaction(address, i == 0 ? value : 0, tag, timestamp); - getTransactions().add(trx); + transactions.add(trx); } } @@ -197,7 +197,6 @@ public class Bundle implements Comparable { * * @param o An object to compare with this object. * @return A value that indicates the relative order of the objects being compared. The return value has the following meanings: Value Meaning Less than zero This object is less than the parameter.Zero This object is equal to . Greater than zero This object is greater than . - */ @Override public int compareTo(Bundle o) { diff --git a/src/main/java/jota/model/Inputs.java b/src/main/java/jota/model/Inputs.java index aad6bb4..8d142e1 100644 --- a/src/main/java/jota/model/Inputs.java +++ b/src/main/java/jota/model/Inputs.java @@ -7,7 +7,7 @@ import java.util.List; /** * This class represents an Inputs. * - * @author Adrian + * @author Adrian **/ public class Inputs { diff --git a/src/main/java/jota/model/Signature.java b/src/main/java/jota/model/Signature.java index de10ef2..02f9b01 100644 --- a/src/main/java/jota/model/Signature.java +++ b/src/main/java/jota/model/Signature.java @@ -50,7 +50,7 @@ public class Signature { /** * Set the signatureFragments. * - * @param signatureFragments The signatureFragments. + * @param signatureFragments The signatureFragments. */ public void setSignatureFragments(List signatureFragments) { this.signatureFragments = signatureFragments; diff --git a/src/main/java/jota/model/Transaction.java b/src/main/java/jota/model/Transaction.java index c6c75d9..4b70683 100644 --- a/src/main/java/jota/model/Transaction.java +++ b/src/main/java/jota/model/Transaction.java @@ -222,6 +222,7 @@ public class Transaction { /** * Set the current index. + * * @param currentIndex The current index. */ public void setCurrentIndex(long currentIndex) { diff --git a/src/main/java/jota/pow/ICurl.java b/src/main/java/jota/pow/ICurl.java index 01ab12c..0608755 100644 --- a/src/main/java/jota/pow/ICurl.java +++ b/src/main/java/jota/pow/ICurl.java @@ -28,7 +28,7 @@ public interface ICurl { /** * Squeezes the specified trits. * - * @param trits The trits. + * @param trits The trits. * @param offset The offset to start from. * @param length The length. * @return The squeezed trits. diff --git a/src/main/java/jota/pow/JCurl.java b/src/main/java/jota/pow/JCurl.java index b23d3d7..3a80848 100644 --- a/src/main/java/jota/pow/JCurl.java +++ b/src/main/java/jota/pow/JCurl.java @@ -2,7 +2,7 @@ package jota.pow; /** * (c) 2016 Come-from-Beyond - * + *

* JCurl belongs to the sponge function family. */ public class JCurl implements ICurl { diff --git a/src/main/java/jota/utils/Checksum.java b/src/main/java/jota/utils/Checksum.java index 7627570..a69c3f9 100644 --- a/src/main/java/jota/utils/Checksum.java +++ b/src/main/java/jota/utils/Checksum.java @@ -34,6 +34,8 @@ public class Checksum { public static String removeChecksum(String address) throws InvalidAddressException { if (isAddressWithChecksum(address)) { return removeChecksumFromAddress(address); + } else if (isAddressWithoutChecksum(address)) { + return address; } throw new InvalidAddressException(); } diff --git a/src/main/java/jota/utils/Converter.java b/src/main/java/jota/utils/Converter.java index 1f80892..4410962 100644 --- a/src/main/java/jota/utils/Converter.java +++ b/src/main/java/jota/utils/Converter.java @@ -49,9 +49,9 @@ public class Converter { /** * Converts the specified trits array to bytes. * - * @param trits The trits. + * @param trits The trits. * @param offset The offset to start from. - * @param size The size. + * @param size The size. * @return The bytes. */ public static byte[] bytes(final int[] trits, final int offset, final int size) { @@ -122,6 +122,7 @@ public class Converter { /** * Converts the specified trinary encoded string into a trits array of the specified length. + * * @param trytes The trytes. * @param length The length. * @return A trits array. @@ -200,7 +201,7 @@ public class Converter { /** * Copies the trits from the input string into the destination array * - * @param input The input String. + * @param input The input String. * @param destination The destination array. * @return The destination. */ @@ -217,9 +218,9 @@ public class Converter { /** * Converts trites to trytes. * - * @param trits Teh trits to be converted. + * @param trits Teh trits to be converted. * @param offset The offset to start from. - * @param size The size. + * @param size The size. * @return The trytes. **/ public static String trytes(final int[] trits, final int offset, final int size) { @@ -244,7 +245,7 @@ public class Converter { /** * Converts the specified trits array to trytes in integer representation. * - * @param trits The trits. + * @param trits The trits. * @param offset The offset to start from. * @return The value. */ @@ -286,7 +287,7 @@ public class Converter { * Increments the specified trits. * * @param trits The trits. - * @param size The size. + * @param size The size. */ public static void increment(final int[] trits, final int size) { diff --git a/src/main/java/jota/utils/InputValidator.java b/src/main/java/jota/utils/InputValidator.java index e3d6a85..7d1686e 100644 --- a/src/main/java/jota/utils/InputValidator.java +++ b/src/main/java/jota/utils/InputValidator.java @@ -55,7 +55,7 @@ public class InputValidator { * * @param trytes The trytes to validate. * @param length The length. - * @return true if the specified string consist only of '9'; otherwise, false. + * @return true if the specified string consist only of '9'; otherwise, false. **/ public static boolean isNinesTrytes(final String trytes, final int length) { return trytes.matches("^[9]{" + (length == 0 ? "0," : length) + "}$"); @@ -77,7 +77,7 @@ public class InputValidator { * @param trytes The trytes array to validate. * @return true if the specified array contains only valid trytes otherwise, false. **/ - public static boolean isArrayOfTrytes(String[] trytes){ + public static boolean isArrayOfTrytes(String[] trytes) { for (String tryte : trytes) { // Check if correct 2673 trytes if (!isTrytes(tryte, 2673)) { diff --git a/src/main/java/jota/utils/IotaAPIUtils.java b/src/main/java/jota/utils/IotaAPIUtils.java index 7916acf..ae2ea2a 100644 --- a/src/main/java/jota/utils/IotaAPIUtils.java +++ b/src/main/java/jota/utils/IotaAPIUtils.java @@ -21,11 +21,11 @@ public class IotaAPIUtils { /** * Generates a new address * - * @param seed The tryte-encoded seed. It should be noted that this seed is not transferred. + * @param seed The tryte-encoded seed. It should be noted that this seed is not transferred. * @param security The secuirty level of private key / seed. - * @param index The index to start search from. If the index is provided, the generation of the address is not deterministic. + * @param index The index to start search from. If the index is provided, the generation of the address is not deterministic. * @param checksum The adds 9-tryte address checksum - * @param curl The curl instance. + * @param curl The curl instance. * @return An String with address. * @throws InvalidAddressException is thrown when the specified address is not an valid address. */ diff --git a/src/main/java/jota/utils/IotaUnitConverter.java b/src/main/java/jota/utils/IotaUnitConverter.java index c9e1cf1..758cbd3 100644 --- a/src/main/java/jota/utils/IotaUnitConverter.java +++ b/src/main/java/jota/utils/IotaUnitConverter.java @@ -12,9 +12,9 @@ public class IotaUnitConverter { /** * Convert the iota amount. * - * @param amount The amount. + * @param amount The amount. * @param fromUnit The source unit e.g. the unit of amount. - * @param toUnit The target unit. + * @param toUnit The target unit. * @return The specified amount in the target unit. **/ public static long convertUnits(long amount, IotaUnits fromUnit, IotaUnits toUnit) { @@ -36,7 +36,7 @@ public class IotaUnitConverter { /** * Convert the iota amount to text. * - * @param amount The amount. + * @param amount The amount. * @param extended Extended length. * @return The specified amount in the target unit. **/ @@ -60,8 +60,8 @@ public class IotaUnitConverter { * Create amount with unit text. * * @param amountInUnit The amount in units. - * @param unit The unit. - * @param extended Extended length. + * @param unit The unit. + * @param extended Extended length. * @return The target unit. **/ private static String createAmountWithUnitDisplayText(double amountInUnit, IotaUnits unit, boolean extended) { @@ -74,8 +74,8 @@ public class IotaUnitConverter { * Create amount text. * * @param amountInUnit The amount in units. - * @param unit The unit. - * @param extended Extended length. + * @param unit The unit. + * @param extended Extended length. * @return The target unit. **/ public static String createAmountDisplayText(double amountInUnit, IotaUnits unit, boolean extended) { diff --git a/src/main/java/jota/utils/Multisig.java b/src/main/java/jota/utils/Multisig.java index e7f3fc7..17ae539 100644 --- a/src/main/java/jota/utils/Multisig.java +++ b/src/main/java/jota/utils/Multisig.java @@ -16,6 +16,7 @@ public class Multisig { public Multisig(ICurl customCurl) { this.curl = customCurl; + this.curl.reset(); this.signingInstance = new Signing(curl.clone()); } @@ -24,14 +25,13 @@ public class Multisig { } /** - * @param seed tryte-encoded seed. It should be noted that this seed is not transferred + * @param seed tryte-encoded seed. It should be noted that this seed is not transferred * @param security security secuirty level of private key / seed * @param index * @return digest trytes **/ - private String getDigest(String seed, int security, int index) { - - int[] key = signingInstance.key(Converter.trits(seed), security, index); + public String getDigest(String seed, int security, int index) { + int[] key = signingInstance.key(Converter.trits(seed, 243), index, security); return Converter.trytes(signingInstance.digests(key)); } @@ -40,21 +40,19 @@ public class Multisig { * * @param digestTrytes * @param curlStateTrytes - * @method addAddressDigest * @return digest trytes + * @method addAddressDigest **/ - private String addAddressDigest(String digestTrytes, String curlStateTrytes, ICurl customCurl) { + public String addAddressDigest(String digestTrytes, String curlStateTrytes) { - int[] digest = Converter.trits(digestTrytes); + + int[] digest = Converter.trits(digestTrytes, digestTrytes.length() * 3); // If curlStateTrytes is provided, convert into trits // else use empty state and initiate the creation of a new address - int[] curlState = curlStateTrytes.isEmpty() ? Converter.trits(curlStateTrytes) : new int[243]; - - - ICurl curl = customCurl == null ? new JCurl() : customCurl; - + int[] curlState = !curlStateTrytes.isEmpty() ? Converter.trits(curlStateTrytes, + digestTrytes.length() * 3) : new int[digestTrytes.length() * 3]; // initialize Curl with the provided state curl.setState(curlState); @@ -67,24 +65,23 @@ public class Multisig { /** * Gets the key value of a seed * - * @param seed tryte-encoded seed. It should be noted that this seed is not transferred + * @param seed tryte-encoded seed. It should be noted that this seed is not transferred * @param index * @return digest trytes **/ - private String getKey(String seed, int index, int security) { + public String getKey(String seed, int index, int security) { - return Converter.trytes(signingInstance.key(Converter.trits(seed), index, security)); + return Converter.trytes(signingInstance.key(Converter.trits(seed, 81 * security), index, security)); } /** * Generates a new address * * @param curlStateTrytes - * @param customCurl * @return address **/ - private String finalizeAddress(String curlStateTrytes, ICurl customCurl) { + public String finalizeAddress(String curlStateTrytes) { int[] curlState = Converter.trits(curlStateTrytes); @@ -103,10 +100,9 @@ public class Multisig { * * @param multisigAddress * @param digests - * @param customCurl * @returns boolean **/ - private boolean validateAddress(String multisigAddress, int[][] digests, ICurl customCurl) { + public boolean validateAddress(String multisigAddress, int[][] digests) { // initialize Curl with the provided state curl.reset(); @@ -131,7 +127,7 @@ public class Multisig { * @param keyTrytes * @return Returns bundle trytes. **/ - private void addSignature(Bundle[] bundleToSign, String inputAddress, String keyTrytes) { + public Bundle addSignature(Bundle bundleToSign, String inputAddress, String keyTrytes) { // Get the security used for the private key @@ -148,66 +144,65 @@ public class Multisig { int numSignedTxs = 0; - for (Bundle bundle : bundleToSign) + for (int i = 0; i < bundleToSign.getTransactions().size(); i++) { - for (int i = 0; i < bundle.getTransactions().size(); i++) { + if (bundleToSign.getTransactions().get(i).getAddress().equals(inputAddress)) { - if (!bundle.getTransactions().get(i).getAddress().equals(inputAddress)) { + // If transaction is already signed, increase counter + if (!InputValidator.isNinesTrytes(bundleToSign.getTransactions().get(i).getSignatureFragments(), + bundleToSign.getTransactions().get(i).getSignatureFragments().length())) { - // If transaction is already signed, increase counter - if (!InputValidator.isNinesTrytes(bundle.getTransactions().get(i).getSignatureFragments(), bundle.getTransactions().get(i).getSignatureFragments().length())) { + numSignedTxs++; + } + // Else sign the transactions + else { - numSignedTxs++; + String bundleHash = bundleToSign.getTransactions().get(i).getBundle(); + + // First 6561 trits for the firstFragment + int[] firstFragment = Arrays.copyOfRange(key, 0, 6561); + + // Get the normalized bundle hash + int[][] normalizedBundleFragments = new int[3][27]; + int[] normalizedBundleHash = bundleToSign.normalizedBundle(bundleHash); + + + // Split hash into 3 fragments + for (int k = 0; k < 3; k++) { + normalizedBundleFragments[k] = Arrays.copyOfRange(normalizedBundleHash, (k * 27), (k + 1) * 27); } - // Else sign the transactions - else { - - String bundleHash = bundle.getTransactions().get(i).getBundle(); - - // First 6561 trits for the firstFragment - int[] firstFragment = Arrays.copyOfRange(key, 0, 6561); - - // Get the normalized bundle hash - int[][] normalizedBundleFragments = new int[3][27]; - int[] normalizedBundleHash = bundle.normalizedBundle(bundleHash); - // Split hash into 3 fragments - for (int k = 0; k < 3; k++) { - normalizedBundleFragments[k] = Arrays.copyOfRange(normalizedBundleHash, (k * 27), (k + 1) * 27); - } + // First bundle fragment uses 27 trytes + int[] firstBundleFragment = normalizedBundleFragments[numSignedTxs % 3]; + // Calculate the new signatureFragment with the first bundle fragment + int[] firstSignedFragment = signingInstance.signatureFragment(firstBundleFragment, firstFragment); - // First bundle fragment uses 27 trytes - int[] firstBundleFragment = normalizedBundleFragments[numSignedTxs % 3]; + // Convert signature to trytes and assign the new signatureFragment + bundleToSign.getTransactions().get(i).setSignatureFragments(Converter.trytes(firstSignedFragment)); + + for (int j = 1; j < security; j++) { + + // Next 6561 trits for the firstFragment + int[] nextFragment = Arrays.copyOfRange(key, 6561 * j, (j + 1) * 6561); + + // Use the next 27 trytes + int[] nextBundleFragment = normalizedBundleFragments[(numSignedTxs + j) % 3]; // Calculate the new signatureFragment with the first bundle fragment - int[] firstSignedFragment = signingInstance.signatureFragment(firstBundleFragment, firstFragment); + int[] nextSignedFragment = signingInstance.signatureFragment(nextBundleFragment, nextFragment); - // Convert signature to trytes and assign the new signatureFragment - bundle.getTransactions().get(i).setSignatureFragments(Converter.trytes(firstSignedFragment)); - - for (int j = 1; j < security; j++) { - - // Next 6561 trits for the firstFragment - int[] nextFragment = Arrays.copyOfRange(key, 6561 * j, (j + 1) * 6561); - - // Use the next 27 trytes - int[] nextBundleFragment = normalizedBundleFragments[(numSignedTxs + j) % 3]; - - // Calculate the new signatureFragment with the first bundle fragment - int[] nextSignedFragment = signingInstance.signatureFragment(nextBundleFragment, nextFragment); - - // Convert signature to trytes and add new bundle entry at i + j position - // Assign the signature fragment - bundle.getTransactions().get(i + j).setSignatureFragments(Converter.trytes(nextSignedFragment)); - } - - break; + // Convert signature to trytes and add new bundle entry at i + j position + // Assign the signature fragment + bundleToSign.getTransactions().get(i + j).setSignatureFragments(Converter.trytes(nextSignedFragment)); } + + break; } } + } - return; + return bundleToSign; } } \ No newline at end of file diff --git a/src/main/java/jota/utils/Parallel.java b/src/main/java/jota/utils/Parallel.java index 0b2556b..7587393 100644 --- a/src/main/java/jota/utils/Parallel.java +++ b/src/main/java/jota/utils/Parallel.java @@ -51,7 +51,6 @@ public class Parallel { } /** - * * @param */ public interface Operation { diff --git a/src/main/java/jota/utils/Signing.java b/src/main/java/jota/utils/Signing.java index 798431b..bd4b6a5 100644 --- a/src/main/java/jota/utils/Signing.java +++ b/src/main/java/jota/utils/Signing.java @@ -1,6 +1,7 @@ package jota.utils; import jota.model.Bundle; +import jota.model.Transaction; import jota.pow.ICurl; import jota.pow.JCurl; @@ -8,6 +9,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; + public class Signing { /** @@ -15,14 +17,25 @@ public class Signing { */ private ICurl curl; - public Signing() { - this(null); - } - + /** + * public Signing() { + * this(null); + * } + *

+ * /** + * + * @param curl + */ public Signing(ICurl curl) { this.curl = curl == null ? new JCurl() : curl; } + /** + * @param seed + * @param index + * @param length + * @return + */ public int[] key(int[] seed, int index, int length) { for (int i = 0; i < index; i++) { @@ -145,6 +158,31 @@ public class Signing { return buffer; } + public Boolean validateSignatures(Bundle signedBundle, String inputAddress) { + String bundleHash = ""; + Transaction trx; + List signatureFragments = new ArrayList<>(); + for (int i = 0; i < signedBundle.getTransactions().size(); i++) { + + trx = signedBundle.getTransactions().get(i); + + if (trx.getAddress().equals(inputAddress)) { + bundleHash = trx.getBundle(); + + // if we reached remainder bundle + String signatureFragment = trx.getSignatureFragments(); + if (InputValidator.isNinesTrytes(signatureFragment, signatureFragment.length())) { + break; + } + signatureFragments.add(signatureFragment); + } + } + + + return validateSignatures(inputAddress, signatureFragments.toArray(new String[signatureFragments.size()]), bundleHash); + } + + public Boolean validateSignatures(String expectedAddress, String[] signatureFragments, String bundleHash) { Bundle bundle = new Bundle(); diff --git a/src/main/java/jota/utils/TrytesConverter.java b/src/main/java/jota/utils/TrytesConverter.java index 0bddd7d..c1c2ac0 100644 --- a/src/main/java/jota/utils/TrytesConverter.java +++ b/src/main/java/jota/utils/TrytesConverter.java @@ -10,20 +10,20 @@ public class TrytesConverter { /** * Conversion of ascii encoded bytes to trytes. * Input is a string (can be stringified JSON object), return value is Trytes - * + *

* How the conversion works: * 2 Trytes === 1 Byte * There are a total of 27 different tryte values: 9ABCDEFGHIJKLMNOPQRSTUVWXYZ - * + *

* 1. We get the decimal value of an individual ASCII character * 2. From the decimal value, we then derive the two tryte values by basically calculating the tryte equivalent (e.g. 100 === 19 + 3 * 27) * a. The first tryte value is the decimal value modulo 27 (27 trytes) * b. The second value is the remainder (decimal value - first value), divided by 27 * 3. The two values returned from Step 2. are then input as indices into the available values list ('9ABCDEFGHIJKLMNOPQRSTUVWXYZ') to get the correct tryte value - * - * + *

+ *

* EXAMPLE - * + *

* Lets say we want to convert the ASCII character "Z". * 1. 'Z' has a decimal value of 90. * 2. 90 can be represented as 9 + 3 * 27. To make it simpler: @@ -34,7 +34,6 @@ public class TrytesConverter { * b. The second tryte value is '9ABCDEFGHIJKLMNOPQRSTUVWXYZ'[3] === "C" * Our tryte pair is "IC" * - * * @param inputString The input String. * @return The ASCII char "Z" is represented as "IC" in trytes. */