Search in sources :

Example 11 with ArgumentException

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);
    }
}
Also used : ArgumentException(jota.error.ArgumentException)

Example 12 with ArgumentException

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());
}
Also used : ICurl(jota.pow.ICurl) ArgumentException(jota.error.ArgumentException)

Example 13 with ArgumentException

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);
    }
}
Also used : ArgumentException(jota.error.ArgumentException)

Example 14 with ArgumentException

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();
}
Also used : Transaction(jota.model.Transaction) ArgumentException(jota.error.ArgumentException)

Example 15 with ArgumentException

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);
        }
    }
}
Also used : ArgumentException(jota.error.ArgumentException)

Aggregations

ArgumentException (jota.error.ArgumentException)19 ApiResponse (run.wallet.iota.api.responses.ApiResponse)10 NetworkError (run.wallet.iota.api.responses.error.NetworkError)10 Address (run.wallet.iota.model.Address)6 ArrayList (java.util.ArrayList)4 Activity (android.app.Activity)3 Bundle (android.os.Bundle)3 Transfer (run.wallet.iota.model.Transfer)3 Wallet (run.wallet.iota.model.Wallet)3 KeyReuseDetectedDialog (run.wallet.iota.ui.dialog.KeyReuseDetectedDialog)3 NotificationManager (android.app.NotificationManager)2 GetNewAddressResponse (jota.dto.response.GetNewAddressResponse)2 RunSendTransferResponse (jota.dto.response.RunSendTransferResponse)2 Input (jota.model.Input)2 Transaction (jota.model.Transaction)2 Transfer (jota.model.Transfer)2 ICurl (jota.pow.ICurl)2 StopWatch (jota.utils.StopWatch)2 GetNewAddressRequest (run.wallet.iota.api.requests.GetNewAddressRequest)2 NudgeRequest (run.wallet.iota.api.requests.NudgeRequest)2