use of jota.error.ArgumentException in project run-wallet-android by runplay.
the class IotaMsg method initiateTransfer.
/**
* 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 remainderAddress Has to be generated by the cosigners before initiating the transfer, can be null if fully spent.
* @return Bundle of transaction objects.
* @throws ArgumentException is thrown when an invalid argument is provided.
* @throws IllegalStateException is thrown when a transfer fails because their is not enough balance to perform the transfer.
*/
public List<Transaction> initiateTransfer(int securitySum, final String inputAddress, String remainderAddress, final List<Transfer> transfers, boolean testMode) throws ArgumentException {
// validate input address
if (!InputValidator.isAddress(inputAddress))
throw new ArgumentException(INVALID_ADDRESSES_INPUT_ERROR);
// validate remainder address
if (remainderAddress != null && !InputValidator.isAddress(remainderAddress)) {
throw new ArgumentException(INVALID_ADDRESSES_INPUT_ERROR);
}
// Input validation of transfers object
if (!InputValidator.isTransfersCollectionValid(transfers)) {
throw new ArgumentException(INVALID_TRANSFERS_INPUT_ERROR);
}
// Create a new bundle
final Bundle bundle = new Bundle();
int totalValue = 0;
final List<String> signatureFragments = new ArrayList<>();
String tag = "";
// and prepare the signatureFragments, message and tag
for (final Transfer transfer : transfers) {
int signatureMessageLength = 1;
// If message longer than 2187 trytes, increase signatureMessageLength (add next transaction)
if (transfer.getMessage().length() > jota.utils.Constants.MESSAGE_LENGTH) {
// Get total length, message / maxLength (2187 trytes)
signatureMessageLength += Math.floor(transfer.getMessage().length() / jota.utils.Constants.MESSAGE_LENGTH);
String msgCopy = transfer.getMessage();
// While there is still a message, copy it
while (!msgCopy.isEmpty()) {
String fragment = StringUtils.substring(msgCopy, 0, jota.utils.Constants.MESSAGE_LENGTH);
msgCopy = StringUtils.substring(msgCopy, jota.utils.Constants.MESSAGE_LENGTH, msgCopy.length());
// Pad remainder of fragment
fragment = StringUtils.rightPad(fragment, jota.utils.Constants.MESSAGE_LENGTH, '9');
signatureFragments.add(fragment);
}
} else {
// Else, get single fragment with 2187 of 9's trytes
String fragment = transfer.getMessage();
if (transfer.getMessage().length() < jota.utils.Constants.MESSAGE_LENGTH) {
fragment = StringUtils.rightPad(fragment, jota.utils.Constants.MESSAGE_LENGTH, '9');
}
signatureFragments.add(fragment);
}
tag = transfer.getTag();
// pad for required 27 tryte length
if (transfer.getTag().length() < jota.utils.Constants.TAG_LENGTH) {
tag = StringUtils.rightPad(tag, jota.utils.Constants.TAG_LENGTH, '9');
}
// get current timestamp in seconds
long timestamp = (long) Math.floor(Calendar.getInstance().getTimeInMillis() / 1000);
// Add first entry to the bundle
bundle.addEntry(signatureMessageLength, transfer.getAddress(), transfer.getValue(), tag, timestamp);
// Sum up total value
totalValue += transfer.getValue();
}
// Get inputs if we are sending tokens
if (totalValue != 0) {
GetBalancesResponse balancesResponse = getBalances(100, Collections.singletonList(inputAddress));
String[] balances = balancesResponse.getBalances();
long totalBalance = 0;
for (String balance : balances) {
long thisBalance = Long.parseLong(balance);
totalBalance += thisBalance;
}
// 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
bundle.addEntry(securitySum, inputAddress, toSubtract, tag, timestamp);
}
// Return not enough balance error
if (totalValue > totalBalance) {
throw new IllegalStateException(NOT_ENOUGH_BALANCE_ERROR);
}
// Add extra output to send remaining funds to
if (totalBalance > totalValue) {
long remainder = totalBalance - totalValue;
// Remainder bundle entry if necessary
if (remainderAddress == null) {
throw new IllegalStateException(NO_REMAINDER_ADDRESS_ERROR);
}
bundle.addEntry(1, remainderAddress, remainder, tag, timestamp);
}
bundle.finalize(SpongeFactory.create(SpongeFactory.Mode.CURLP81));
bundle.addTrytes(signatureFragments);
return bundle.getTransactions();
} else {
throw new RuntimeException(INVALID_VALUE_TRANSFER_ERROR);
}
}
use of jota.error.ArgumentException in project run-wallet-android by runplay.
the class RunIotaAPI method getBundle.
/**
* Gets the associated bundle transactions of a single transaction.
* Does validation of signatures, total sum as well as bundle order.
*
* @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 the specified input is not valid.
*/
public GetBundleResponse getBundle(String transaction) throws ArgumentException {
if (!InputValidator.isHash(transaction)) {
throw new ArgumentException(INVALID_HASHES_INPUT_ERROR);
}
Bundle bundle = traverseBundle(transaction, null, new Bundle());
if (bundle == null) {
throw new ArgumentException(INVALID_BUNDLE_ERROR);
}
StopWatch stopWatch = new StopWatch();
long totalSum = 0;
String bundleHash = bundle.getTransactions().get(0).getBundle();
ICurl curl = SpongeFactory.create(SpongeFactory.Mode.KERL);
curl.reset();
List<Signature> signaturesToValidate = new ArrayList<>();
for (int i = 0; i < bundle.getTransactions().size(); i++) {
Transaction trx = bundle.getTransactions().get(i);
Long bundleValue = trx.getValue();
totalSum += bundleValue;
if (i != bundle.getTransactions().get(i).getCurrentIndex()) {
throw new ArgumentException(INVALID_BUNDLE_ERROR);
}
String trxTrytes = trx.toTrytes().substring(2187, 2187 + 162);
// Absorb bundle hash + value + timestamp + lastIndex + currentIndex trytes.
curl.absorb(Converter.trits(trxTrytes));
// Check if input transaction
if (bundleValue < 0) {
String address = trx.getAddress();
Signature sig = new Signature();
sig.setAddress(address);
sig.getSignatureFragments().add(trx.getSignatureFragments());
// Find the subsequent txs with the remaining signature fragment
for (int y = i + 1; y < bundle.getTransactions().size(); y++) {
Transaction newBundleTx = bundle.getTransactions().get(y);
// Check if new tx is part of the signature fragment
if (newBundleTx.getAddress().equals(address) && newBundleTx.getValue() == 0) {
if (sig.getSignatureFragments().indexOf(newBundleTx.getSignatureFragments()) == -1)
sig.getSignatureFragments().add(newBundleTx.getSignatureFragments());
}
}
signaturesToValidate.add(sig);
}
}
// Check for total sum, if not equal 0 return error
if (totalSum != 0)
throw new ArgumentException(INVALID_BUNDLE_SUM_ERROR);
int[] bundleFromTrxs = new int[243];
curl.squeeze(bundleFromTrxs);
String bundleFromTxString = Converter.trytes(bundleFromTrxs);
// Check if bundle hash is the same as returned by tx object
if (!bundleFromTxString.equals(bundleHash))
throw new ArgumentException(INVALID_BUNDLE_HASH_ERROR);
// Last tx in the bundle should have currentIndex === lastIndex
bundle.setLength(bundle.getTransactions().size());
if (!(bundle.getTransactions().get(bundle.getLength() - 1).getCurrentIndex() == (bundle.getTransactions().get(bundle.getLength() - 1).getLastIndex())))
throw new ArgumentException(INVALID_BUNDLE_ERROR);
// Validate the signatures
for (Signature aSignaturesToValidate : signaturesToValidate) {
String[] signatureFragments = aSignaturesToValidate.getSignatureFragments().toArray(new String[aSignaturesToValidate.getSignatureFragments().size()]);
String address = aSignaturesToValidate.getAddress();
boolean isValidSignature = new Signing(customCurl.clone()).validateSignatures(address, signatureFragments, bundleHash);
if (!isValidSignature)
throw new ArgumentException(INVALID_SIGNATURES_ERROR);
}
return GetBundleResponse.create(bundle.getTransactions(), stopWatch.getElapsedTimeMili());
}
use of jota.error.ArgumentException in project run-wallet-android by runplay.
the class RunIotaAPI method initiateTransfer.
/**
* 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 remainderAddress Has to be generated by the cosigners before initiating the transfer, can be null if fully spent.
* @return Bundle of transaction objects.
* @throws ArgumentException is thrown when an invalid argument is provided.
* @throws IllegalStateException is thrown when a transfer fails because their is not enough balance to perform the transfer.
*/
public List<Transaction> initiateTransfer(int securitySum, final String inputAddress, String remainderAddress, final List<Transfer> transfers, boolean testMode) throws ArgumentException {
// validate input address
if (!InputValidator.isAddress(inputAddress))
throw new ArgumentException(INVALID_ADDRESSES_INPUT_ERROR);
// validate remainder address
if (remainderAddress != null && !InputValidator.isAddress(remainderAddress)) {
throw new ArgumentException(INVALID_ADDRESSES_INPUT_ERROR);
}
// Input validation of transfers object
if (!InputValidator.isTransfersCollectionValid(transfers)) {
throw new ArgumentException(INVALID_TRANSFERS_INPUT_ERROR);
}
// Create a new bundle
final Bundle bundle = new Bundle();
int totalValue = 0;
final List<String> signatureFragments = new ArrayList<>();
String tag = "";
// and prepare the signatureFragments, message and tag
for (final Transfer transfer : transfers) {
// remove the checksum of the address if provided
if (Checksum.isValidChecksum(transfer.getAddress())) {
transfer.setAddress(Checksum.removeChecksum(transfer.getAddress()));
}
int signatureMessageLength = 1;
// If message longer than 2187 trytes, increase signatureMessageLength (add next transaction)
if (transfer.getMessage().length() > Constants.MESSAGE_LENGTH) {
// Get total length, message / maxLength (2187 trytes)
signatureMessageLength += Math.floor(transfer.getMessage().length() / Constants.MESSAGE_LENGTH);
String msgCopy = transfer.getMessage();
// While there is still a message, copy it
while (!msgCopy.isEmpty()) {
String fragment = StringUtils.substring(msgCopy, 0, Constants.MESSAGE_LENGTH);
msgCopy = StringUtils.substring(msgCopy, Constants.MESSAGE_LENGTH, msgCopy.length());
// Pad remainder of fragment
fragment = StringUtils.rightPad(fragment, Constants.MESSAGE_LENGTH, '9');
signatureFragments.add(fragment);
}
} else {
// Else, get single fragment with 2187 of 9's trytes
String fragment = transfer.getMessage();
if (transfer.getMessage().length() < Constants.MESSAGE_LENGTH) {
fragment = StringUtils.rightPad(fragment, Constants.MESSAGE_LENGTH, '9');
}
signatureFragments.add(fragment);
}
tag = transfer.getTag();
// pad for required 27 tryte length
if (transfer.getTag().length() < Constants.TAG_LENGTH) {
tag = StringUtils.rightPad(tag, Constants.TAG_LENGTH, '9');
}
// get current timestamp in seconds
long timestamp = (long) Math.floor(Calendar.getInstance().getTimeInMillis() / 1000);
// Add first entry to the bundle
bundle.addEntry(signatureMessageLength, transfer.getAddress(), transfer.getValue(), tag, timestamp);
// Sum up total value
totalValue += transfer.getValue();
}
// Get inputs if we are sending tokens
if (totalValue != 0) {
GetBalancesResponse balancesResponse = getBalances(100, Collections.singletonList(inputAddress));
String[] balances = balancesResponse.getBalances();
long totalBalance = 0;
for (String balance : balances) {
long thisBalance = Long.parseLong(balance);
totalBalance += thisBalance;
}
// 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
bundle.addEntry(securitySum, inputAddress, toSubtract, tag, timestamp);
}
// Return not enough balance error
if (totalValue > totalBalance) {
throw new IllegalStateException(NOT_ENOUGH_BALANCE_ERROR);
}
// Add extra output to send remaining funds to
if (totalBalance > totalValue) {
long remainder = totalBalance - totalValue;
// Remainder bundle entry if necessary
if (remainderAddress == null) {
throw new IllegalStateException(NO_REMAINDER_ADDRESS_ERROR);
}
bundle.addEntry(1, remainderAddress, remainder, tag, timestamp);
}
bundle.finalize(SpongeFactory.create(SpongeFactory.Mode.CURLP81));
bundle.addTrytes(signatureFragments);
return bundle.getTransactions();
} else {
throw new RuntimeException(INVALID_VALUE_TRANSFER_ERROR);
}
}
use of jota.error.ArgumentException in project run-wallet-android by runplay.
the class RunIotaAPICore method attachToTangle.
/**
* Attaches the specified transactions (trytes) to the Tangle by doing Proof of Work.
*
* @param trunkTransaction The trunk transaction to approve.
* @param branchTransaction The branch transaction to approve.
* @param minWeightMagnitude The Proof of Work intensity.
* @param trytes A List of trytes (raw transaction data) to attach to the tangle.
*/
public GetAttachToTangleResponse attachToTangle(String trunkTransaction, String branchTransaction, Integer minWeightMagnitude, String... trytes) throws ArgumentException {
if (!InputValidator.isHash(trunkTransaction)) {
throw new ArgumentException(INVALID_HASHES_INPUT_ERROR);
}
if (!InputValidator.isHash(branchTransaction)) {
throw new ArgumentException(INVALID_HASHES_INPUT_ERROR);
}
if (!InputValidator.isArrayOfTrytes(trytes)) {
throw new ArgumentException(INVALID_TRYTES_INPUT_ERROR);
}
if (localPoW != null) {
final String[] resultTrytes = new String[trytes.length];
String previousTransaction = null;
for (int i = 0; i < trytes.length; i++) {
Transaction txn = new Transaction(trytes[i]);
txn.setTrunkTransaction(previousTransaction == null ? trunkTransaction : previousTransaction);
txn.setBranchTransaction(previousTransaction == null ? branchTransaction : trunkTransaction);
if (txn.getTag().isEmpty() || txn.getTag().matches("9*"))
txn.setTag(txn.getObsoleteTag());
txn.setAttachmentTimestamp(System.currentTimeMillis());
txn.setAttachmentTimestampLowerBound(0);
txn.setAttachmentTimestampUpperBound(3_812_798_742_493L);
resultTrytes[i] = localPoW.performPoW(txn.toTrytes(), minWeightMagnitude);
previousTransaction = new Transaction(resultTrytes[i]).getHash();
}
return new GetAttachToTangleResponse(resultTrytes);
}
final Call<GetAttachToTangleResponse> res = service.attachToTangle(IotaAttachToTangleRequest.createAttachToTangleRequest(trunkTransaction, branchTransaction, minWeightMagnitude, trytes));
return wrapCheckedException(res).body();
}
use of jota.error.ArgumentException in project run-wallet-android by runplay.
the class RunIotaAPI method validateTransfersAddresses.
/**
* @param seed Tryte-encoded seed
* @param security The security level of private key / seed.
* @param trytes The trytes.
* @throws ArgumentException is thrown when the specified input is not valid.
*/
public void validateTransfersAddresses(String seed, int security, List<String> trytes) throws ArgumentException {
HashSet<String> addresses = new HashSet<>();
List<Transaction> inputTransactions = new ArrayList<>();
List<String> inputAddresses = new ArrayList<>();
for (String trx : trytes) {
addresses.add(new Transaction(trx, customCurl.clone()).getAddress());
inputTransactions.add(new Transaction(trx, customCurl.clone()));
}
String[] hashes = findTransactionsByAddresses(addresses.toArray(new String[addresses.size()])).getHashes();
List<Transaction> transactions = findTransactionsObjectsByHashes(hashes);
GetNewAddressResponse gna = getNewAddress(seed, security, 0, false, 0, true);
GetBalancesAndFormatResponse gbr = getInputs(seed, security, 0, 0, 0);
for (Input input : gbr.getInputs()) {
inputAddresses.add(input.getAddress());
}
// check if send to input
for (Transaction trx : inputTransactions) {
if (trx.getValue() > 0 && inputAddresses.contains(trx.getAddress()))
throw new ArgumentException(SEND_TO_INPUTS_ERROR);
}
for (Transaction trx : transactions) {
// check if destination address is already in use
if (trx.getValue() < 0 && !inputAddresses.contains(trx.getAddress())) {
throw new ArgumentException(Constants.SENDING_TO_USED_ADDRESS_ERROR);
}
// check if key reuse
if (trx.getValue() < 0 && gna.getAddresses().contains(trx.getAddress())) {
throw new ArgumentException(Constants.PRIVATE_KEY_REUSE_ERROR);
}
}
}
Aggregations