Still experimenting. This donation is randomly attached so as to not have a consistent fingerprint, and is also occasionally split into 2 outputs.

This also sets the foundation for a pay-to-many feature in the future for users.
This commit is contained in:
pokkst 2022-12-03 23:25:06 -06:00
parent fd84f11848
commit 8782d212a3
No known key found for this signature in database
GPG key ID: 90C2ED85E67A50FF
5 changed files with 33 additions and 12 deletions

View file

@ -246,7 +246,6 @@ std::vector<std::uint64_t> java2cpp_long(JNIEnv *env, jlongArray longArray) {
for (jint i = 0; i < len; i++) { for (jint i = 0; i < len; i++) {
jlong amount = getElement(env, longArray, i); jlong amount = getElement(env, longArray, i);
result.emplace_back(amount); result.emplace_back(amount);
env->ReleaseLongArrayElements(longArray, reinterpret_cast<jlong *>(amount), i);
} }
return result; return result;
} }

View file

@ -310,7 +310,7 @@ public class Wallet {
return pendingTransaction; return pendingTransaction;
} }
public PendingTransaction createTransactionMultDest(ArrayList<TransactionOutput> outputs, PendingTransaction.Priority priority, ArrayList<String> key_images) { public PendingTransaction createTransactionMultDest(List<TransactionOutput> outputs, PendingTransaction.Priority priority, ArrayList<String> key_images) {
disposePendingTransaction(); disposePendingTransaction();
int _priority = priority.getValue(); int _priority = priority.getValue();
ArrayList<String> destinations = new ArrayList<>(); ArrayList<String> destinations = new ArrayList<>();

View file

@ -30,6 +30,7 @@ import net.mynero.wallet.util.Constants;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/** /**
@ -131,47 +132,62 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
public PendingTransaction createTx(String address, String amountStr, boolean sendAll, PendingTransaction.Priority feePriority, ArrayList<String> selectedUtxos) throws Exception { public PendingTransaction createTx(String address, String amountStr, boolean sendAll, PendingTransaction.Priority feePriority, ArrayList<String> selectedUtxos) throws Exception {
long amount = Wallet.getAmountFromString(amountStr); long amount = Wallet.getAmountFromString(amountStr);
System.out.println("AMOUNT:: " + amount);
ArrayList<String> preferredInputs; ArrayList<String> preferredInputs;
if (selectedUtxos.isEmpty()) { if (selectedUtxos.isEmpty()) {
// no inputs manually selected, we are sending from home screen most likely, or user somehow broke the app // no inputs manually selected, we are sending from home screen most likely, or user somehow broke the app
preferredInputs = UTXOService.getInstance().selectUtxos(amount, sendAll); preferredInputs = UTXOService.getInstance().selectUtxos(amount, sendAll);
} else { } else {
preferredInputs = selectedUtxos; preferredInputs = selectedUtxos;
checkSelectedAmounts(selectedUtxos, amount, sendAll); checkSelectedAmounts(preferredInputs, amount, sendAll);
} }
if(sendAll) { if(sendAll) {
return wallet.createSweepTransaction(address, feePriority, preferredInputs); return wallet.createSweepTransaction(address, feePriority, preferredInputs);
} }
boolean donatePerTx = PrefService.getInstance().getBoolean(Constants.PREF_DONATE_PER_TX, false);
ArrayList<TransactionOutput> outputs = new ArrayList<>(); ArrayList<TransactionOutput> outputs = new ArrayList<>();
outputs.add(new TransactionOutput(address, amount)); outputs.add(new TransactionOutput(address, amount));
if(donatePerTx) { List<TransactionOutput> finalOutputs = maybeAddDonationOutputs(amount, outputs, preferredInputs);
return wallet.createTransactionMultDest(finalOutputs, feePriority, preferredInputs);
}
private List<TransactionOutput> maybeAddDonationOutputs(long amount, List<TransactionOutput> outputs, List<String> preferredInputs) throws Exception {
TransactionOutput mainDestination = outputs.get(0); // at this point, for now, we should only have one item in the list
String paymentId = Wallet.getPaymentIdFromAddress(mainDestination.getDestination(), WalletManager.getInstance().getNetworkType().getValue());
System.out.println("PAYMENT ID:: " + paymentId + ".");
ArrayList<TransactionOutput> newOutputs = new ArrayList<>(outputs);
boolean donatePerTx = true;
if(donatePerTx && paymentId.isEmpty()) {
float randomDonatePct = getRandomDonateAmount(0.0075f, 0.015f); // occasionally attaches a 0.75% to 1.5% fee. It is random so that not even I know how much exactly you are sending. float randomDonatePct = getRandomDonateAmount(0.0075f, 0.015f); // occasionally attaches a 0.75% to 1.5% fee. It is random so that not even I know how much exactly you are sending.
/* /*
It's also not entirely "per tx". It won't always attach it so as to not have a consistent fingerprint on-chain. When it does attach a donation, It's also not entirely "per tx". It won't always attach it so as to not have a consistent fingerprint on-chain. When it does attach a donation,
it will periodically split it up into 2 outputs instead of 1. it will periodically split it up into 2 outputs instead of 1.
*/ */
System.out.println("RANDOM DONATE PCT:: " + randomDonatePct);
int attachDonationRoll = new SecureRandom().nextInt(100); int attachDonationRoll = new SecureRandom().nextInt(100);
if(attachDonationRoll > 75) { if(attachDonationRoll > 1) {
int splitDonationRoll = new SecureRandom().nextInt(100); int splitDonationRoll = new SecureRandom().nextInt(100);
long donateAmount = (long) (amount*randomDonatePct); long donateAmount = (long) (amount*randomDonatePct);
System.out.println("DONATE AMOUNT:: " + donateAmount);
if(splitDonationRoll > 50) { if(splitDonationRoll > 50) {
// split // split
long splitAmount = donateAmount / 2; long splitAmount = donateAmount / 2;
outputs.add(new TransactionOutput(Constants.DONATE_ADDRESS, splitAmount)); newOutputs.add(new TransactionOutput(Constants.DONATE_ADDRESS, splitAmount));
outputs.add(new TransactionOutput(Constants.DONATE_ADDRESS, splitAmount)); newOutputs.add(new TransactionOutput(Constants.DONATE_ADDRESS_2, splitAmount));
} else { } else {
outputs.add(new TransactionOutput(Constants.DONATE_ADDRESS, donateAmount)); newOutputs.add(new TransactionOutput(Constants.DONATE_ADDRESS, donateAmount));
} }
checkSelectedAmounts(selectedUtxos, amount+donateAmount, false); // check that the selected UTXOs satisfy the new amount total long total = amount + donateAmount;
System.out.println("TOTAL:: " + total);
checkSelectedAmounts(preferredInputs, total, false); // check that the selected UTXOs satisfy the new amount total
} }
} }
return wallet.createTransactionMultDest(outputs, feePriority, preferredInputs);
return newOutputs;
} }
private void checkSelectedAmounts(ArrayList<String> selectedUtxos, long amount, boolean sendAll) throws Exception { private void checkSelectedAmounts(List<String> selectedUtxos, long amount, boolean sendAll) throws Exception {
if (!sendAll) { if (!sendAll) {
long amountSelected = 0; long amountSelected = 0;
for (CoinsInfo coinsInfo : UTXOService.getInstance().getUtxos()) { for (CoinsInfo coinsInfo : UTXOService.getInstance().getUtxos()) {
@ -181,6 +197,9 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
} }
if (amountSelected <= amount) { if (amountSelected <= amount) {
System.out.println("/////// CHECK");
System.out.println("AMOUNT SELECTED:: " + amountSelected);
System.out.println("AMOUNT:: " + amount);
throw new Exception("insufficient wallet balance"); throw new Exception("insufficient wallet balance");
} }
} }

View file

@ -63,6 +63,8 @@ public class UTXOService extends ServiceBase {
} }
} }
System.out.println("AMOUNT WITH BASIC FEE:: " + amountWithBasicFee);
System.out.println("AMOUNT SELECTED:: " + amountSelected);
if (amountSelected < amountWithBasicFee && !sendAll) { if (amountSelected < amountWithBasicFee && !sendAll) {
throw new Exception("insufficient wallet balance"); throw new Exception("insufficient wallet balance");
} }

View file

@ -20,5 +20,6 @@ public class Constants {
public static final String NAV_ARG_TXINFO = "nav_arg_txinfo"; public static final String NAV_ARG_TXINFO = "nav_arg_txinfo";
public static final String STREET_MODE_BALANCE = "#.############"; public static final String STREET_MODE_BALANCE = "#.############";
public static final String DONATE_ADDRESS_2 = "89Yym1JTqiM7PMgra3XP1oMtGkiAQHBrFE7VJFAVYU1DTpAqviTsNewM2KoBw5fLLufaNMfJZq9bNhyPmfWq62hy4T9jzQF";
public static final String DONATE_ADDRESS = "87MRtZPrWUCVUgcFHdsVb5MoZUcLtqfD3FvQVGwftFb8eSdMnE39JhAJcbuSW8X2vRaRsB9RQfuCpFciybJFHaz3QYPhCLw"; public static final String DONATE_ADDRESS = "87MRtZPrWUCVUgcFHdsVb5MoZUcLtqfD3FvQVGwftFb8eSdMnE39JhAJcbuSW8X2vRaRsB9RQfuCpFciybJFHaz3QYPhCLw";
} }