Skip to content

Commit

Permalink
add privacy-focused anti-fee-sniping recommendations for taproot tran…
Browse files Browse the repository at this point in the history
…sactions
  • Loading branch information
craigraw committed Sep 22, 2021
1 parent 38783d6 commit c9e57fa
Showing 1 changed file with 25 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,10 @@ public WalletTransaction createWalletTransaction(List<UtxoSelector> utxoSelector
txInput.setSequenceNumber(TransactionInput.SEQUENCE_RBF_ENABLED);
}

if(getScriptType() == P2TR && currentBlockHeight != null) {
applySequenceAntiFeeSniping(transaction, selectedUtxos, currentBlockHeight);
}

for(int i = 1; i < numSets; i+=2) {
WalletNode mixNode = getFreshNode(KeyPurpose.CHANGE);
txExcludedChangeNodes.add(mixNode);
Expand Down Expand Up @@ -794,6 +798,27 @@ public WalletTransaction createWalletTransaction(List<UtxoSelector> utxoSelector
}
}

private void applySequenceAntiFeeSniping(Transaction transaction, Map<BlockTransactionHashIndex, WalletNode> selectedUtxos, int currentBlockHeight) {
Random random = new Random();
boolean locktime = random.nextInt(2) == 0 || getScriptType() != P2TR || selectedUtxos.keySet().stream().anyMatch(utxo -> utxo.getConfirmations(currentBlockHeight) > 65535);

if(locktime) {
transaction.setLocktime(currentBlockHeight);
if(random.nextInt(10) == 0) {
transaction.setLocktime(Math.max(0, currentBlockHeight - random.nextInt(100)));
}
} else {
transaction.setLocktime(0);
int inputIndex = random.nextInt(transaction.getInputs().size());
TransactionInput txInput = transaction.getInputs().get(inputIndex);
BlockTransactionHashIndex utxo = selectedUtxos.keySet().stream().filter(ref -> ref.getHash().equals(txInput.getOutpoint().getHash()) && ref.getIndex() == txInput.getOutpoint().getIndex()).findFirst().orElseThrow();
txInput.setSequenceNumber(utxo.getConfirmations(currentBlockHeight));
if(random.nextInt(10) == 0) {
txInput.setSequenceNumber(Math.max(0, txInput.getSequenceNumber() - random.nextInt(100)));
}
}
}

private List<Long> getSetChangeAmounts(List<Map<BlockTransactionHashIndex, WalletNode>> selectedUtxoSets, long totalPaymentAmount, long feeRequiredAmt) {
List<Long> changeAmts = new ArrayList<>();
int numSets = selectedUtxoSets.size();
Expand Down

0 comments on commit c9e57fa

Please sign in to comment.