mirror of
https://github.com/gosticks/iota.lib.java.git
synced 2026-10-04 05:26:59 +00:00
allow the injection of custom curl implementations
This commit is contained in:
@@ -10,7 +10,6 @@ import jota.pow.JCurl;
|
||||
import jota.utils.*;
|
||||
import jota.utils.StopWatch;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -69,7 +68,7 @@ public class IotaAPI {
|
||||
// and return the list of all addresses
|
||||
if (total != 0) {
|
||||
for (int i = index; i < index + total; i++) {
|
||||
allAddresses.add(IotaAPIUtils.newAddress(seed, i, checksum));
|
||||
allAddresses.add(IotaAPIUtils.newAddress(seed, i, checksum, customCurl));
|
||||
}
|
||||
return GetNewAddressResponse.create(allAddresses, stopWatch.getElapsedTimeMili());
|
||||
}
|
||||
@@ -77,7 +76,7 @@ public class IotaAPI {
|
||||
// already created if null, return list of addresses
|
||||
for (int i = index; ; i++) {
|
||||
|
||||
final String newAddress = IotaAPIUtils.newAddress(seed, i, checksum);
|
||||
final String newAddress = IotaAPIUtils.newAddress(seed, i, checksum, customCurl);
|
||||
final FindTransactionResponse response = coreProxy.findTransactionsByAddresses(newAddress);
|
||||
|
||||
allAddresses.add(newAddress);
|
||||
@@ -247,7 +246,7 @@ public class IotaAPI {
|
||||
final List<Transaction> trx = new ArrayList<>();
|
||||
|
||||
for (final String tx : Arrays.asList(res.getTrytes())) {
|
||||
trx.add(Converter.transactionObject(tx));
|
||||
trx.add(new TransactionConverter(customCurl).transactionObject(tx));
|
||||
}
|
||||
return trx;
|
||||
}
|
||||
@@ -273,7 +272,7 @@ public class IotaAPI {
|
||||
final List<Transaction> trxs = new ArrayList<>();
|
||||
|
||||
for (final String tryte : trytesResponse.getTrytes()) {
|
||||
trxs.add(Converter.transactionObject(tryte));
|
||||
trxs.add(new TransactionConverter(customCurl).transactionObject(tryte));
|
||||
}
|
||||
return trxs;
|
||||
}
|
||||
@@ -456,7 +455,7 @@ public class IotaAPI {
|
||||
} else {
|
||||
|
||||
// If no input required, don't sign and simply finalize the bundle
|
||||
bundle.finalize();
|
||||
bundle.finalize(customCurl);
|
||||
bundle.addTrytes(signatureFragments);
|
||||
|
||||
List<Transaction> trxb = bundle.getTransactions();
|
||||
@@ -509,7 +508,7 @@ public class IotaAPI {
|
||||
|
||||
for (int i = start; i < end; i++) {
|
||||
|
||||
String address = IotaAPIUtils.newAddress(seed, i, false);
|
||||
String address = IotaAPIUtils.newAddress(seed, i, false, customCurl);
|
||||
allAddresses.add(address);
|
||||
}
|
||||
|
||||
@@ -644,7 +643,7 @@ public class IotaAPI {
|
||||
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();
|
||||
boolean isValidSignature = Signing.validateSignatures(address, signatureFragments, bundleHash);
|
||||
boolean isValidSignature = new Signing().validateSignatures(address, signatureFragments, bundleHash);
|
||||
|
||||
if (!isValidSignature) throw new InvalidSignatureException();
|
||||
}
|
||||
@@ -744,7 +743,7 @@ public class IotaAPI {
|
||||
throw new ArgumentException("Bundle transactions not visible");
|
||||
}
|
||||
|
||||
Transaction trx = Converter.transactionObject(gtr.getTrytes()[0]);
|
||||
Transaction trx = new TransactionConverter(customCurl).transactionObject(gtr.getTrytes()[0]);
|
||||
if (trx == null || trx.getBundle() == null) {
|
||||
throw new ArgumentException("Invalid trytes, could not create object");
|
||||
}
|
||||
@@ -785,7 +784,7 @@ public class IotaAPI {
|
||||
throw new ArgumentException("Bundle transactions not visible");
|
||||
}
|
||||
|
||||
Transaction trx = Converter.transactionObject(gtr.getTrytes()[0]);
|
||||
Transaction trx = new TransactionConverter(customCurl).transactionObject(gtr.getTrytes()[0]);
|
||||
if (trx == null || trx.getBundle() == null) {
|
||||
throw new ArgumentException("Invalid trytes, could not create object");
|
||||
}
|
||||
@@ -821,7 +820,7 @@ public class IotaAPI {
|
||||
// Remainder bundle entry
|
||||
bundle.addEntry(1, remainderAddress, remainder, tag, timestamp);
|
||||
// Final function for signing inputs
|
||||
return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments);
|
||||
return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments, customCurl);
|
||||
} else if (remainder > 0) {
|
||||
// Generate a new Address by calling getNewAddress
|
||||
|
||||
@@ -830,11 +829,11 @@ public class IotaAPI {
|
||||
bundle.addEntry(1, res.getAddresses().get(0), remainder, tag, timestamp);
|
||||
|
||||
// Final function for signing inputs
|
||||
return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments);
|
||||
return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments, customCurl);
|
||||
} else {
|
||||
// If there is no remainder, do not add transaction to bundle
|
||||
// simply sign and return
|
||||
return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments);
|
||||
return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments, customCurl);
|
||||
}
|
||||
|
||||
// If multiple inputs provided, subtract the totalTransferValue by
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package jota.model;
|
||||
|
||||
import jota.pow.ICurl;
|
||||
import jota.pow.JCurl;
|
||||
import jota.utils.Converter;
|
||||
|
||||
@@ -54,9 +55,9 @@ public class Bundle implements Comparable {
|
||||
}
|
||||
}
|
||||
|
||||
public void finalize() {
|
||||
public void finalize(ICurl customCurl) {
|
||||
|
||||
JCurl curl = new JCurl();
|
||||
ICurl curl = customCurl == null ? new JCurl() : customCurl;
|
||||
curl.reset();
|
||||
|
||||
for (int i = 0; i < this.getTransactions().size(); i++) {
|
||||
|
||||
@@ -165,4 +165,5 @@ public class Transaction {
|
||||
if (((Transaction) obj).getHash().equals(this.getHash())) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -246,46 +246,4 @@ public class Converter {
|
||||
+ trx.getNonce();
|
||||
}
|
||||
|
||||
public static Transaction transactionObject(final String trytes) {
|
||||
|
||||
if (StringUtils.isEmpty(trytes)) {
|
||||
log.warn("Warning: empty trytes in input for transactionObject");
|
||||
return null;
|
||||
}
|
||||
|
||||
// validity check
|
||||
for (int i = 2279; i < 2295; i++) {
|
||||
if (trytes.charAt(i) != '9') {
|
||||
log.warn("Trytes {} does not seem a valid tryte", trytes);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
int[] transactionTrits = Converter.trits(trytes);
|
||||
int[] hash = new int[243];
|
||||
|
||||
final JCurl curl = new JCurl(); // we need a fluent JCurl.
|
||||
|
||||
// generate the correct transaction hash
|
||||
curl.reset();
|
||||
curl.absorbb(transactionTrits, 0, transactionTrits.length);
|
||||
curl.squeezee(hash, 0, hash.length);
|
||||
|
||||
Transaction trx = new Transaction();
|
||||
|
||||
trx.setHash(Converter.trytes(hash));
|
||||
trx.setSignatureFragments(trytes.substring(0, 2187));
|
||||
trx.setAddress(trytes.substring(2187, 2268));
|
||||
trx.setValue("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 6804, 6837)));
|
||||
trx.setTag(trytes.substring(2295, 2322));
|
||||
trx.setTimestamp("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 6966, 6993)));
|
||||
trx.setCurrentIndex("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 6993, 7020)));
|
||||
trx.setLastIndex("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 7020, 7047)));
|
||||
trx.setBundle(trytes.substring(2349, 2430));
|
||||
trx.setTrunkTransaction(trytes.substring(2430, 2511));
|
||||
trx.setBranchTransaction(trytes.substring(2511, 2592));
|
||||
trx.setNonce(trytes.substring(2592, 2673));
|
||||
|
||||
return trx;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package jota.utils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import jota.pow.ICurl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -26,11 +27,11 @@ public class IotaAPIUtils {
|
||||
* @param checksum
|
||||
* @return an String with address
|
||||
*/
|
||||
public static String newAddress(String seed, int index, boolean checksum) {
|
||||
|
||||
final int[] key = Signing.key(Converter.trits(seed), index, 2);
|
||||
final int[] digests = Signing.digests(key);
|
||||
final int[] addressTrits = Signing.address(digests);
|
||||
public static String newAddress(String seed, int index, boolean checksum, ICurl curl) {
|
||||
Signing signing = new Signing(curl);
|
||||
final int[] key = signing.key(Converter.trits(seed), index, 2);
|
||||
final int[] digests = signing.digests(key);
|
||||
final int[] addressTrits = signing.address(digests);
|
||||
|
||||
String address = Converter.trytes(addressTrits);
|
||||
|
||||
@@ -43,8 +44,8 @@ public class IotaAPIUtils {
|
||||
public static List<String> signInputsAndReturn(final String seed,
|
||||
final List<Input> inputs,
|
||||
final Bundle bundle,
|
||||
final List<String> signatureFragments) {
|
||||
bundle.finalize();
|
||||
final List<String> signatureFragments, ICurl curl) {
|
||||
bundle.finalize(curl);
|
||||
bundle.addTrytes(signatureFragments);
|
||||
|
||||
// SIGNING OF INPUTS
|
||||
@@ -68,7 +69,7 @@ public class IotaAPIUtils {
|
||||
String bundleHash = bundle.getTransactions().get(i).getBundle();
|
||||
|
||||
// Get corresponding private key of address
|
||||
int[] key = Signing.key(Converter.trits(seed), keyIndex, 2);
|
||||
int[] key = new Signing(curl).key(Converter.trits(seed), keyIndex, 2);
|
||||
|
||||
// First 6561 trits for the firstFragment
|
||||
int[] firstFragment = Arrays.copyOfRange(key, 0, 6561);
|
||||
@@ -80,7 +81,7 @@ public class IotaAPIUtils {
|
||||
int[] firstBundleFragment = Arrays.copyOfRange(normalizedBundleHash, 0, 27);
|
||||
|
||||
// Calculate the new signatureFragment with the first bundle fragment
|
||||
int[] firstSignedFragment = Signing.signatureFragment(firstBundleFragment, firstFragment);
|
||||
int[] firstSignedFragment = new Signing(curl).signatureFragment(firstBundleFragment, firstFragment);
|
||||
|
||||
// Convert signature to trytes and assign the new signatureFragment
|
||||
bundle.getTransactions().get(i).setSignatureFragments(Converter.trytes(firstSignedFragment));
|
||||
@@ -97,7 +98,7 @@ public class IotaAPIUtils {
|
||||
int[] secondBundleFragment = Arrays.copyOfRange(normalizedBundleHash, 27, 27 * 2);
|
||||
|
||||
// Calculate the new signature
|
||||
int[] secondSignedFragment = Signing.signatureFragment(secondBundleFragment, secondFragment);
|
||||
int[] secondSignedFragment = new Signing(curl).signatureFragment(secondBundleFragment, secondFragment);
|
||||
|
||||
// Convert signature to trytes and assign it again to this bundle entry
|
||||
bundle.getTransactions().get(j).setSignatureFragments(Converter.trytes(secondSignedFragment));
|
||||
|
||||
@@ -5,11 +5,21 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import jota.model.Bundle;
|
||||
import jota.pow.ICurl;
|
||||
import jota.pow.JCurl;
|
||||
|
||||
public class Signing {
|
||||
private ICurl curl;
|
||||
|
||||
static int[] key(int[] seed, int index, int length) {
|
||||
public Signing() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public Signing(ICurl curl) {
|
||||
this.curl = curl == null ? new JCurl() : curl;
|
||||
}
|
||||
|
||||
public int[] key(int[] seed, int index, int length) {
|
||||
|
||||
for (int i = 0; i < index; i++) {
|
||||
for (int j = 0; j < 243; j++) {
|
||||
@@ -21,7 +31,6 @@ public class Signing {
|
||||
}
|
||||
}
|
||||
|
||||
final JCurl curl = new JCurl();
|
||||
curl.reset();
|
||||
curl.absorbb(seed, 0, seed.length);
|
||||
curl.squeezee(seed, 0, seed.length);
|
||||
@@ -44,7 +53,7 @@ public class Signing {
|
||||
return to(key);
|
||||
}
|
||||
|
||||
private static int[] to(List<Integer> key) {
|
||||
private int[] to(List<Integer> key) {
|
||||
int a[] = new int[key.size()];
|
||||
int i = 0;
|
||||
for (Integer v : key) {
|
||||
@@ -53,21 +62,19 @@ public class Signing {
|
||||
return a;
|
||||
}
|
||||
|
||||
public static int[] signatureFragment(int[] normalizedBundleFragment, int[] keyFragment) {
|
||||
public int[] signatureFragment(int[] normalizedBundleFragment, int[] keyFragment) {
|
||||
|
||||
int[] signatureFragment = keyFragment;
|
||||
int[] hash;
|
||||
|
||||
JCurl curl = new JCurl();
|
||||
|
||||
for (int i = 0; i < 27; i++) {
|
||||
|
||||
hash = Arrays.copyOfRange(signatureFragment, i * 243, (i + 1) * 243);
|
||||
|
||||
for (int j = 0; j < 13 - normalizedBundleFragment[i]; j++) {
|
||||
curl.reset()
|
||||
.absorbb(hash, 0, hash.length)
|
||||
.squeezee(hash, 0, hash.length);
|
||||
.absorbb(hash, 0, hash.length)
|
||||
.squeezee(hash, 0, hash.length);
|
||||
}
|
||||
|
||||
for (int j = 0; j < 243; j++) {
|
||||
@@ -78,17 +85,15 @@ public class Signing {
|
||||
return signatureFragment;
|
||||
}
|
||||
|
||||
public static int[] address(int[] digests) {
|
||||
final JCurl curl = new JCurl();
|
||||
public int[] address(int[] digests) {
|
||||
int[] address = new int[243];
|
||||
curl.reset()
|
||||
.absorbb(digests)
|
||||
.squeezee(address);
|
||||
.absorbb(digests)
|
||||
.squeezee(address);
|
||||
return address;
|
||||
}
|
||||
|
||||
public static int[] digests(int[] key) {
|
||||
final JCurl curl = new JCurl();
|
||||
|
||||
public int[] digests(int[] key) {
|
||||
|
||||
int[] digests = new int[(int) Math.floor(key.length / 6561) * 243];
|
||||
int[] buffer = new int[243];
|
||||
@@ -101,8 +106,8 @@ public class Signing {
|
||||
buffer = Arrays.copyOfRange(keyFragment, j * 243, (j + 1) * 243);
|
||||
for (int k = 0; k < 26; k++) {
|
||||
curl.reset()
|
||||
.absorbb(buffer)
|
||||
.squeezee(buffer);
|
||||
.absorbb(buffer)
|
||||
.squeezee(buffer);
|
||||
}
|
||||
System.arraycopy(buffer, 0, keyFragment, j * 243, 243);
|
||||
}
|
||||
@@ -116,18 +121,16 @@ public class Signing {
|
||||
return digests;
|
||||
}
|
||||
|
||||
public static int[] digest(int[] normalizedBundleFragment, int[] signatureFragment) {
|
||||
|
||||
public int[] digest(int[] normalizedBundleFragment, int[] signatureFragment) {
|
||||
curl.reset();
|
||||
int[] buffer = new int[243];
|
||||
|
||||
JCurl curl = new JCurl().reset();
|
||||
|
||||
for (int i = 0; i < 27; i++) {
|
||||
buffer = Arrays.copyOfRange(signatureFragment, i * 243, (i + 1) * 243);
|
||||
|
||||
for (int j = normalizedBundleFragment[i] + 13; j-- > 0; ) {
|
||||
|
||||
JCurl jCurl = new JCurl();
|
||||
ICurl jCurl = new JCurl();
|
||||
jCurl.reset();
|
||||
jCurl.absorbb(buffer);
|
||||
jCurl.squeezee(buffer);
|
||||
@@ -139,7 +142,7 @@ public class Signing {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static Boolean validateSignatures(String expectedAddress, String[] signatureFragments, String bundleHash) {
|
||||
public Boolean validateSignatures(String expectedAddress, String[] signatureFragments, String bundleHash) {
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package jota.utils;
|
||||
|
||||
import jota.model.Transaction;
|
||||
import jota.pow.ICurl;
|
||||
import jota.pow.JCurl;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by Adrian on 15.01.2017.
|
||||
*/
|
||||
public class TransactionConverter {
|
||||
private static final Logger log = LoggerFactory.getLogger(TransactionConverter.class);
|
||||
private ICurl customCurl;
|
||||
|
||||
public TransactionConverter(ICurl curl) {
|
||||
customCurl = curl;
|
||||
}
|
||||
|
||||
public TransactionConverter() {
|
||||
customCurl = null;
|
||||
}
|
||||
|
||||
public Transaction transactionObject(final String trytes) {
|
||||
|
||||
if (StringUtils.isEmpty(trytes)) {
|
||||
log.warn("Warning: empty trytes in input for transactionObject");
|
||||
return null;
|
||||
}
|
||||
|
||||
// validity check
|
||||
for (int i = 2279; i < 2295; i++) {
|
||||
if (trytes.charAt(i) != '9') {
|
||||
log.warn("Trytes {} does not seem a valid tryte", trytes);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
int[] transactionTrits = Converter.trits(trytes);
|
||||
int[] hash = new int[243];
|
||||
|
||||
final JCurl curl = new JCurl(); // we need a fluent JCurl.
|
||||
|
||||
// generate the correct transaction hash
|
||||
curl.reset();
|
||||
curl.absorbb(transactionTrits, 0, transactionTrits.length);
|
||||
curl.squeezee(hash, 0, hash.length);
|
||||
|
||||
Transaction trx = new Transaction();
|
||||
|
||||
trx.setHash(Converter.trytes(hash));
|
||||
trx.setSignatureFragments(trytes.substring(0, 2187));
|
||||
trx.setAddress(trytes.substring(2187, 2268));
|
||||
trx.setValue("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 6804, 6837)));
|
||||
trx.setTag(trytes.substring(2295, 2322));
|
||||
trx.setTimestamp("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 6966, 6993)));
|
||||
trx.setCurrentIndex("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 6993, 7020)));
|
||||
trx.setLastIndex("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 7020, 7047)));
|
||||
trx.setBundle(trytes.substring(2349, 2430));
|
||||
trx.setTrunkTransaction(trytes.substring(2430, 2511));
|
||||
trx.setBranchTransaction(trytes.substring(2511, 2592));
|
||||
trx.setNonce(trytes.substring(2592, 2673));
|
||||
|
||||
return trx;
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ public class IotaAPITest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void shouldSendTrytes() {
|
||||
iotaClient.sendTrytes(new String[]{TEST_TRYTES}, 9, 18);
|
||||
@@ -145,5 +145,5 @@ public class IotaAPITest {
|
||||
SendTransferResponse str = iotaClient.sendTransfer(TEST_SEED2, 9, 18, transfers, null, null);
|
||||
assertThat(str.getSuccessfully(), IsNull.notNullValue());
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
Reference in New Issue
Block a user