This commit is contained in:
AZ 2017-01-15 20:45:46 +01:00
parent 327c3bbf72
commit a27168dee0
22 changed files with 217 additions and 95 deletions

View File

@ -63,11 +63,6 @@
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>
<build>

View File

@ -8,7 +8,6 @@ import jota.model.*;
import jota.pow.ICurl;
import jota.pow.JCurl;
import jota.utils.*;
import jota.utils.StopWatch;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -28,26 +27,17 @@ import java.util.*;
*
* @author davassi
*/
public class IotaAPI {
public class IotaAPI extends IotaAPICoreProxy {
private static final Logger log = LoggerFactory.getLogger(IotaAPI.class);
private IotaAPICoreProxy coreProxy;
private ICurl customCurl;
private StopWatch stopWatch;
public IotaAPI() {
this(null);
protected IotaAPI(Builder builder) {
super(builder);
customCurl = builder.customCurl;
}
public IotaAPI(ICurl customCurl) {
this.customCurl = customCurl;
coreProxy = new IotaAPICoreProxy.Builder().build();
stopWatch = new StopWatch();
}
// end of proxied calls.
/**
* 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
@ -77,7 +67,7 @@ public class IotaAPI {
for (int i = index; ; i++) {
final String newAddress = IotaAPIUtils.newAddress(seed, i, checksum, customCurl);
final FindTransactionResponse response = coreProxy.findTransactionsByAddresses(newAddress);
final FindTransactionResponse response = findTransactionsByAddresses(newAddress);
allAddresses.add(newAddress);
if (response.getHashes().length == 0) {
@ -168,7 +158,7 @@ public class IotaAPI {
if (inclusionStates) {
try {
gisr = getLatestInclusion(tailTxArray);
} catch (IllegalAccessError e) {
} catch (IllegalAccessError ignored) {
}
if (gisr == null || gisr.getStates() == null || gisr.getStates().length == 0)
@ -213,12 +203,12 @@ public class IotaAPI {
public StoreTransactionsResponse broadcastAndStore(final String... trytes) {
try {
coreProxy.broadcastTransactions(trytes);
broadcastTransactions(trytes);
} catch (Exception e) {
log.error("Impossible to broadcastAndStore, aborting.", e);
throw new IllegalStateException("BroadcastAndStore Illegal state Exception");
}
return coreProxy.storeTransactions(trytes);
return storeTransactions(trytes);
}
/**
@ -230,10 +220,10 @@ public class IotaAPI {
* @return
*/
public List<Transaction> sendTrytes(final String[] trytes, final int depth, final int minWeightMagnitude) {
final GetTransactionsToApproveResponse txs = coreProxy.getTransactionsToApprove(depth);
final GetTransactionsToApproveResponse txs = getTransactionsToApprove(depth);
// attach to tangle - do pow
final GetAttachToTangleResponse res = coreProxy.attachToTangle(txs.getTrunkTransaction(), txs.getBranchTransaction(), minWeightMagnitude, trytes);
final GetAttachToTangleResponse res = attachToTangle(txs.getTrunkTransaction(), txs.getBranchTransaction(), minWeightMagnitude, trytes);
try {
broadcastAndStore(res.getTrytes());
@ -267,7 +257,7 @@ public class IotaAPI {
throw new IllegalStateException("Not an Array of Hashes: " + Arrays.toString(hashes));
}
final GetTrytesResponse trytesResponse = coreProxy.getTrytes(hashes);
final GetTrytesResponse trytesResponse = getTrytes(hashes);
final List<Transaction> trxs = new ArrayList<>();
@ -288,7 +278,7 @@ public class IotaAPI {
* @returns {object} success
**/
public List<Transaction> findTransactionObjects(String[] input) {
FindTransactionResponse ftr = coreProxy.findTransactions(input, null, null, null);
FindTransactionResponse ftr = findTransactions(input, null, null, null);
if (ftr == null || ftr.getHashes() == null)
return null;
@ -307,7 +297,7 @@ public class IotaAPI {
* @returns {object} success
**/
public List<Transaction> findTransactionObjectsByBundle(String[] input) {
FindTransactionResponse ftr = coreProxy.findTransactions(null, null, null, input);
FindTransactionResponse ftr = findTransactions(null, null, null, input);
if (ftr == null || ftr.getHashes() == null)
return null;
@ -416,7 +406,7 @@ public class IotaAPI {
inputsAddresses.add(i.getAddress());
}
GetBalancesResponse balancesResponse = coreProxy.getBalances(100, inputsAddresses);
GetBalancesResponse balancesResponse = getBalances(100, inputsAddresses);
String[] balances = balancesResponse.getBalances();
List<Input> confirmedInputs = new ArrayList<>();
@ -448,7 +438,7 @@ public class IotaAPI {
// confirm that the inputs exceed the threshold
else {
GetBalancesAndFormatResponse newinputs = getInputs(seed, Collections.EMPTY_LIST, 0, 0, totalValue);
@SuppressWarnings("unchecked") GetBalancesAndFormatResponse newinputs = getInputs(seed, Collections.EMPTY_LIST, 0, 0, totalValue);
// If inputs with enough balance
return addRemainder(seed, newinputs.getInput(), bundle, tag, totalValue, null, signatureFragments);
}
@ -530,13 +520,13 @@ public class IotaAPI {
public GetBalancesAndFormatResponse getBalanceAndFormat(final List<String> addresses, List<String> balances, long threshold, int start, int end, StopWatch stopWatch) {
if (balances == null || balances.isEmpty()) {
GetBalancesResponse getBalancesResponse = coreProxy.getBalances(100, addresses);
GetBalancesResponse getBalancesResponse = getBalances(100, addresses);
balances = Arrays.asList(getBalancesResponse.getBalances());
}
// If threshold defined, keep track of whether reached or not
// else set default to true
boolean thresholdReached = threshold != 0 ? false : true;
boolean thresholdReached = threshold == 0;
int i = -1;
List<Input> inputs = new ArrayList<>();
@ -640,9 +630,9 @@ public class IotaAPI {
throw new InvalidBundleException("Invalid Bundle");
// Validate the signatures
for (int i = 0; i < signaturesToValidate.size(); i++) {
String[] signatureFragments = signaturesToValidate.get(i).getSignatureFragments().toArray(new String[signaturesToValidate.get(i).getSignatureFragments().size()]);
String address = signaturesToValidate.get(i).getAddress();
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);
if (!isValidSignature) throw new InvalidSignatureException();
@ -679,7 +669,7 @@ public class IotaAPI {
for (int i = 0; i < trxs.size(); i++) {
final FindTransactionResponse response = coreProxy.findTransactionsByBundles(trxs.get(i).getBundle());
final FindTransactionResponse response = findTransactionsByBundles(trxs.get(i).getBundle());
successful[i] = response.getHashes().length != 0;
@ -697,12 +687,12 @@ public class IotaAPI {
* @returns {array} state
**/
public GetInclusionStateResponse getLatestInclusion(String[] hashes) {
GetNodeInfoResponse getNodeInfoResponse = coreProxy.getNodeInfo();
GetNodeInfoResponse getNodeInfoResponse = getNodeInfo();
if (getNodeInfoResponse == null) return null;
String[] latestMilestone = {getNodeInfoResponse.getLatestSolidSubtangleMilestone()};
return coreProxy.getInclusionStates(hashes, latestMilestone);
return getInclusionStates(hashes, latestMilestone);
}
public SendTransferResponse sendTransfer(String seed, int depth, int minWeightMagnitude, final List<Transfer> transfers, Input[] inputs, String address) {
@ -715,7 +705,7 @@ public class IotaAPI {
for (int i = 0; i < trxs.size(); i++) {
final FindTransactionResponse response = coreProxy.findTransactionsByBundles(trxs.get(i).getBundle());
final FindTransactionResponse response = findTransactionsByBundles(trxs.get(i).getBundle());
successful[i] = response.getHashes().length != 0;
}
@ -735,7 +725,7 @@ public class IotaAPI {
* @returns {array} bundle Transaction objects
**/
public Bundle traverseBundle(String trunkTx, String bundleHash, Bundle bundle) throws ArgumentException {
GetTrytesResponse gtr = coreProxy.getTrytes(trunkTx);
GetTrytesResponse gtr = getTrytes(trunkTx);
if (gtr != null) {
@ -776,7 +766,7 @@ public class IotaAPI {
}
public String findTailTransactionHash(String hash) throws ArgumentException {
GetTrytesResponse gtr = coreProxy.getTrytes(hash);
GetTrytesResponse gtr = getTrytes(hash);
if (gtr == null) throw new ArgumentException("Invalid hash");
@ -844,4 +834,18 @@ public class IotaAPI {
}
return null;
}
public static class Builder extends IotaAPICoreProxy.Builder<Builder> {
private ICurl customCurl;
public Builder withCustomCurl(ICurl curl) {
customCurl = curl;
return this;
}
public IotaAPI build() {
super.build();
return new IotaAPI(this);
}
}
}

View File

@ -28,7 +28,7 @@ public class IotaAPICoreProxy {
private IotaAPIService service;
private String protocol, host, port;
private IotaAPICoreProxy(final Builder builder) {
protected IotaAPICoreProxy(final Builder builder) {
protocol = builder.protocol;
host = builder.host;
port = builder.port;
@ -52,7 +52,7 @@ public class IotaAPICoreProxy {
}
}
private static final String env(String env, String def) {
private static String env(String env, String def) {
final String value = System.getenv(env);
if (value == null) {
log.warn("Environment variable '{}' is not defined, and actual value has not been specified. "
@ -187,7 +187,8 @@ public class IotaAPICoreProxy {
return wrapCheckedException(res).body();
}
public static class Builder {
@SuppressWarnings("unchecked")
public static class Builder <T extends Builder<T>> {
String protocol, host, port;
@ -241,19 +242,19 @@ public class IotaAPICoreProxy {
port = env("IOTA_NODE_PORT", "14265");
}
public Builder host(String host) {
public T host(String host) {
this.host = host;
return this;
return (T) this;
}
public Builder port(String port) {
public T port(String port) {
this.port = port;
return this;
return (T) this;
}
public Builder protocol(String protocol) {
public T protocol(String protocol) {
this.protocol = protocol;
return this;
return (T) this;
}
}

View File

@ -20,4 +20,36 @@ public class IotaAttachToTangleRequest extends IotaCommandRequest {
public static IotaAttachToTangleRequest createAttachToTangleRequest(final String trunkTransaction, final String branchTransaction, final Integer minWeightMagnitude, final String... trytes) {
return new IotaAttachToTangleRequest(trunkTransaction, branchTransaction, minWeightMagnitude, trytes);
}
public String getTrunkTransaction() {
return trunkTransaction;
}
public void setTrunkTransaction(String trunkTransaction) {
this.trunkTransaction = trunkTransaction;
}
public String getBranchTransaction() {
return branchTransaction;
}
public void setBranchTransaction(String branchTransaction) {
this.branchTransaction = branchTransaction;
}
public Integer getMinWeightMagnitude() {
return minWeightMagnitude;
}
public void setMinWeightMagnitude(Integer minWeightMagnitude) {
this.minWeightMagnitude = minWeightMagnitude;
}
public String[] getTrytes() {
return trytes;
}
public void setTrytes(String[] trytes) {
this.trytes = trytes;
}
}

View File

@ -14,4 +14,12 @@ public class IotaBroadcastTransactionRequest extends IotaCommandRequest {
public static IotaBroadcastTransactionRequest createBroadcastTransactionsRequest(final String... trytes) {
return new IotaBroadcastTransactionRequest(trytes);
}
public String[] getTrytes() {
return trytes;
}
public void setTrytes(String[] trytes) {
this.trytes = trytes;
}
}

View File

@ -4,6 +4,38 @@ import jota.IotaAPICommands;
public class IotaFindTransactionsRequest extends IotaCommandRequest {
public String[] getBundles() {
return bundles;
}
public void setBundles(String[] bundles) {
this.bundles = bundles;
}
public String[] getAddresses() {
return addresses;
}
public void setAddresses(String[] addresses) {
this.addresses = addresses;
}
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public String[] getApprovees() {
return approvees;
}
public void setApprovees(String[] approvees) {
this.approvees = approvees;
}
private String[] bundles; // List of bundle hashes. The hashes need to be extended to 81chars by padding the hash with 9's.
private String[] addresses;
private String[] tags;

View File

@ -17,5 +17,20 @@ public class IotaGetBalancesRequest extends IotaCommandRequest {
return new IotaGetBalancesRequest(threshold, addresses);
}
public String[] getAddresses() {
return addresses;
}
public void setAddresses(String[] addresses) {
this.addresses = addresses;
}
public Integer getThreshold() {
return threshold;
}
public void setThreshold(Integer threshold) {
this.threshold = threshold;
}
}

View File

@ -25,4 +25,19 @@ public class IotaGetInclusionStateRequest extends IotaCommandRequest {
tips.toArray(new String[]{}));
}
public String[] getTransactions() {
return transactions;
}
public void setTransactions(String[] transactions) {
this.transactions = transactions;
}
public String[] getTips() {
return tips;
}
public void setTips(String[] tips) {
this.tips = tips;
}
}

View File

@ -14,4 +14,12 @@ public class IotaGetTransactionsToApproveRequest extends IotaCommandRequest {
public static IotaGetTransactionsToApproveRequest createIotaGetTransactionsToApproveRequest(Integer depth) {
return new IotaGetTransactionsToApproveRequest(depth);
}
public Integer getDepth() {
return depth;
}
public void setDepth(Integer depth) {
this.depth = depth;
}
}

View File

@ -14,4 +14,12 @@ public class IotaGetTrytesRequest extends IotaCommandRequest {
public static IotaGetTrytesRequest createGetTrytesRequest(String... hashes) {
return new IotaGetTrytesRequest(hashes);
}
public String[] getHashes() {
return hashes;
}
public void setHashes(String[] hashes) {
this.hashes = hashes;
}
}

View File

@ -18,5 +18,13 @@ public class IotaNeighborsRequest extends IotaCommandRequest {
public static IotaNeighborsRequest createRemoveNeighborsRequest(String... uris) {
return new IotaNeighborsRequest(IotaAPICommands.REMOVE_NEIGHBORS, uris);
}
public String[] getUris() {
return uris;
}
public void setUris(String[] uris) {
this.uris = uris;
}
}

View File

@ -14,4 +14,12 @@ public class IotaStoreTransactionsRequest extends IotaCommandRequest {
public static IotaStoreTransactionsRequest createStoreTransactionsRequest(final String... trytes) {
return new IotaStoreTransactionsRequest(trytes);
}
public String[] getTrytes() {
return trytes;
}
public void setTrytes(String[] trytes) {
this.trytes = trytes;
}
}

View File

@ -7,7 +7,7 @@ import java.util.List;
public class AnalyzeTransactionResponse extends AbstractResponse {
private List<Transaction> transactions = new ArrayList<Transaction>();
private List<Transaction> transactions = new ArrayList<>();
public List<Transaction> getTransactions() {
return transactions;

View File

@ -159,11 +159,7 @@ public class Transaction {
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (((Transaction) obj).getHash().equals(this.getHash())) return true;
return false;
return obj != null && ((Transaction) obj).getHash().equals(this.getHash());
}
}

View File

@ -4,12 +4,19 @@ package jota.pow;
* Created by Adrian on 07.01.2017.
*/
public interface ICurl {
public JCurl absorbb(final int[] trits, int offset, int length);
public JCurl absorbb(final int[] trits);
public int[] squeezee(final int[] trits, int offset, int length);
public int[] squeezee(final int[] trits);
public JCurl transform();
public JCurl reset();
public int[] getState();
public void setState(int[] state);
}
JCurl absorbb(final int[] trits, int offset, int length);
JCurl absorbb(final int[] trits);
int[] squeezee(final int[] trits, int offset, int length);
int[] squeezee(final int[] trits);
JCurl transform();
JCurl reset();
int[] getState();
void setState(int[] state);
}

View File

@ -1,8 +1,6 @@
package jota.utils;
import jota.model.Transaction;
import jota.pow.JCurl;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -73,7 +71,7 @@ public class Converter {
int[] ret = new int[integers.size()];
for (int i=0; i < ret.length; i++)
{
ret[i] = integers.get(i).intValue();
ret[i] = integers.get(i);
}
return ret;
}

View File

@ -2,9 +2,6 @@ package jota.utils;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import jota.model.Transaction;
import jota.model.Transfer;
import org.apache.commons.lang3.math.NumberUtils;
@ -81,11 +78,7 @@ public class InputValidator {
}
// Check if tag is correct trytes of {0,27} trytes
if (!isTrytes(transfer.getTag(), 27)) {
return false;
}
return true;
return isTrytes(transfer.getTag(), 27);
}
public static String validateSeed(String seed) {

View File

@ -59,9 +59,9 @@ public class IotaAPIUtils {
// Get the corresponding keyIndex of the address
int keyIndex = 0;
for (int k = 0; k < inputs.size(); k++) {
if (inputs.get(k).getAddress().equals(thisAddress)) {
keyIndex = inputs.get(k).getKeyIndex();
for (Input input : inputs) {
if (input.getAddress().equals(thisAddress)) {
keyIndex = input.getKeyIndex();
break;
}
}
@ -90,7 +90,7 @@ public class IotaAPIUtils {
// find the second transaction to add the remainder of the signature
for (int j = 0; j < bundle.getTransactions().size(); j++) {
// Same address as well as value = 0 (as we already spent the input)
if (bundle.getTransactions().get(j).getAddress() == thisAddress && Long.parseLong(bundle.getTransactions().get(j).getValue()) == 0) {
if (bundle.getTransactions().get(j).getAddress().equals(thisAddress) && Long.parseLong(bundle.getTransactions().get(j).getValue()) == 0) {
// Use the second 6562 trits
int[] secondFragment = Arrays.copyOfRange(key, 6561, 6561 * 2);

View File

@ -1,9 +1,5 @@
package jota.utils;
/**
* Created by pinpong on 30.11.16.
*/
/**
* Table of IOTA units based off of the standard system of Units
**/

View File

@ -25,7 +25,7 @@ public class Parallel {
}
public static <T> Collection<Callable<Void>> createCallables(final Iterable<T> elements, final Operation<T> operation) {
List<Callable<Void>> callables = new LinkedList<Callable<Void>>();
List<Callable<Void>> callables = new LinkedList<>();
for (final T elem : elements) {
callables.add(new Callable<Void>() {
@Override
@ -39,7 +39,7 @@ public class Parallel {
return callables;
}
public static interface Operation<T> {
public void perform(T pParameter);
public interface Operation<T> {
void perform(T pParameter);
}
}

View File

@ -64,12 +64,11 @@ public class Signing {
public int[] signatureFragment(int[] normalizedBundleFragment, int[] keyFragment) {
int[] signatureFragment = keyFragment;
int[] hash;
for (int i = 0; i < 27; i++) {
hash = Arrays.copyOfRange(signatureFragment, i * 243, (i + 1) * 243);
hash = Arrays.copyOfRange(keyFragment, i * 243, (i + 1) * 243);
for (int j = 0; j < 13 - normalizedBundleFragment[i]; j++) {
curl.reset()
@ -78,11 +77,11 @@ public class Signing {
}
for (int j = 0; j < 243; j++) {
signatureFragment[i * 243 + j] = hash[j];
System.arraycopy(hash, j, keyFragment, i * 243 + j, 1);
}
}
return signatureFragment;
return keyFragment;
}
public int[] address(int[] digests) {
@ -162,8 +161,7 @@ public class Signing {
int[] digestBuffer = digest(normalizedBundleFragments[i % 3], Converter.trits(signatureFragments[i]));
for (int j = 0; j < 243; j++) {
digests[i * 243 + j] = digestBuffer[j];
System.arraycopy(digestBuffer, j, digests, i * 243 + j, 1);
}
}
String address = Converter.trytes(address(digests));

View File

@ -65,12 +65,12 @@ public class IotaAPITest {
@Before
public void createApiClientInstance() {
iotaClient = new IotaAPI();
iotaClient = new IotaAPI.Builder().build();
}
@Test
public void shouldCreateIotaApiProxyInstanceWithDefaultValues() {
IotaAPI proxy = new IotaAPI();
IotaAPI proxy = new IotaAPI.Builder().build();
assertThat(proxy, IsNull.notNullValue());
}