Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(coinjoin): mix balance #235

Merged
merged 16 commits into from
Dec 17, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
86f840c
fix: prevent NPE in CoinJoinExtension.getKeyUsage
HashEngineering Oct 30, 2023
23ed876
fix: increase context thread context pool size
HashEngineering Oct 30, 2023
9273f59
fix(coinjoin): reduce logging
HashEngineering Oct 30, 2023
2366273
fix: allow the MasternodeAddress to be nullible in onSessionComplete
HashEngineering Oct 30, 2023
2bda02f
fix: detect the end of mixing based on createDenominated result
HashEngineering Oct 30, 2023
5badb91
feat: add setters for denom goal and hardcap in CoinJoinClientOptions
HashEngineering Nov 3, 2023
73a5bab
refactor: merge both CoinJoinTransactionType classes
HashEngineering Nov 13, 2023
ceab89a
refactor: make TransactionDestination derived from Message
HashEngineering Nov 14, 2023
863545d
fix(coinjoin): Reuse unused keys and prevent using the same key twice
HashEngineering Nov 14, 2023
ae67df6
fix: change the way IsCollateralValid determines if the collateral wa…
HashEngineering Nov 21, 2023
e8f70e0
fix: add session state and short key usage to coinjoin-report
HashEngineering Nov 21, 2023
81d987c
fix(wallettool): improve WalletTool for recovery phrase restoration a…
HashEngineering Nov 21, 2023
90193fa
fix: prevent NPE in CoinJoinExtension.addUnusedKey
HashEngineering Nov 21, 2023
2e87d07
fix(coinjoin): prevent NPE if session is null
HashEngineering Nov 21, 2023
0e65fdd
Merge branch 'feature-coinjoin' of https://github.com/dashevo/dashj i…
HashEngineering Dec 12, 2023
467a19f
fix(coinjoin): set look ahead size to 300 in CoinJoinExtension keychains
HashEngineering Dec 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions core/src/main/java/org/bitcoinj/coinjoin/CoinJoin.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ public static boolean isCollateralValid(Transaction txCollateral) {
return isCollateralValid(txCollateral, true);
}

// TODO: consider IS Locks with InstantSendManager.isLocked(input)?
public static boolean isCollateralValid(Transaction txCollateral, boolean checkInputs) {
if (txCollateral.getOutputs().isEmpty()) {
log.info("coinjoin: Collateral invalid due to no outputs: {}", txCollateral.getTxId());
Expand Down Expand Up @@ -175,6 +176,10 @@ public static boolean isCollateralValid(Transaction txCollateral, boolean checkI
for (TransactionInput txin : txCollateral.getInputs()) {
Transaction tx = txin.getConnectedTransaction();
if (tx != null) {
if (tx.getOutput(txin.getOutpoint().getIndex()).getSpentBy() != null) {
log.info("coinjoin: spent or non-locked mempool input! txin={}", txin);
return false;
}
nValueIn = nValueIn.add(tx.getOutput(txin.getOutpoint().getIndex()).getValue());
} else {
log.info("coinjoin: -- Unknown inputs in collateral transaction, txCollateral={}", txCollateral); /* Continued */
Expand All @@ -189,15 +194,7 @@ public static boolean isCollateralValid(Transaction txCollateral, boolean checkI
}
}

// the collateral tx must not have been seen on the network
TransactionConfidence confidence = txCollateral.getConfidence();
boolean hasBeenSeen = confidence.getConfidenceType() != TransactionConfidence.ConfidenceType.UNKNOWN ||
confidence.numBroadcastPeers() > 0 || confidence.getIXType() != TransactionConfidence.IXType.IX_NONE;
if (hasBeenSeen) {
log.info("coinjoin: collateral has been spent, need to recreate txCollateral={}", txCollateral.getTxId());
}
log.info("coinjoin: collateral: {}", txCollateral); /* Continued */
return !hasBeenSeen;
return true;
}
public static Coin getCollateralAmount() { return getSmallestDenomination().div(10); }
public static Coin getMaxCollateralAmount() { return getCollateralAmount().multiply(4); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.StoredBlock;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.Utils;
import org.bitcoinj.core.VerificationException;
import org.bitcoinj.core.listeners.NewBestBlockListener;
import org.bitcoinj.evolution.Masternode;
Expand Down Expand Up @@ -211,6 +212,9 @@ public String getSessionDenoms() {
}
}

private long lastTimeReportTooRecent = 0;
private long lastMasternodesUsed = 0;

/// Passively run mixing in the background according to the configuration in settings
public boolean doAutomaticDenominating() {
return doAutomaticDenominating(false);
Expand All @@ -234,7 +238,13 @@ public boolean doAutomaticDenominating(boolean dryRun) {
// If we've used 90% of the Masternode list then drop the oldest first ~30%
int thresholdHigh = (int) (mnCountEnabled * 0.9);
int thresholdLow = (int) (thresholdHigh * 0.7);
log.info("Checking masternodesUsed: size: {}, threshold: {}", masternodesUsed.size(), thresholdHigh);

if (!waitForAnotherBlock()) {
if (masternodesUsed.size() != lastMasternodesUsed) {
log.info("Checking masternodesUsed: size: {}, threshold: {}", masternodesUsed.size(), thresholdHigh);
lastMasternodesUsed = masternodesUsed.size();
}
}

if (masternodesUsed.size() > thresholdHigh) {
// remove the first masternodesUsed.size() - thresholdLow masternodes
Expand Down Expand Up @@ -279,8 +289,11 @@ public boolean doAutomaticDenominating(boolean dryRun) {
if (!checkAutomaticBackup()) return false;

if (waitForAnotherBlock()) {
strAutoDenomResult = "Last successful action was too recent.";
log.info("DoAutomaticDenominating -- {}", strAutoDenomResult);
if (Utils.currentTimeMillis() - lastTimeReportTooRecent > 15000 ) {
strAutoDenomResult = "Last successful action was too recent.";
log.info("DoAutomaticDenominating -- {}", strAutoDenomResult);
lastTimeReportTooRecent = Utils.currentTimeMillis();
}
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ public static void setAmount(Coin amount) {
get().coinJoinAmount.set(amount);
}

public static void setDenomsGoal(int goal) { get().coinJoinDenomsGoal.set(goal); }
public static void setDenomsHardCap(int hardCap) { get().coinJoinDenomsHardCap.set(hardCap); }

public static boolean isEnabled() { return CoinJoinClientOptions.get().enableCoinJoin.get(); }
public static boolean isMultiSessionEnabled() { return CoinJoinClientOptions.get().isCoinJoinMultiSession.get(); }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void processDSQueue(Peer from, CoinJoinQueue dsq, boolean enable_bip61) {
}
if (q.isReady() == dsq.isReady() && q.getProTxHash().equals(dsq.getProTxHash())) {
// no way the same mn can send another dsq with the same readiness this soon
log.info("coinjoin: DSQUEUE -- Peer {} is sending WAY too many dsq messages for a masternode {}", from.getAddress().getAddr(), dsq.getProTxHash());
log.debug("coinjoin: DSQUEUE -- Peer {} is sending WAY too many dsq messages for a masternode {}", from.getAddress().getAddr(), dsq.getProTxHash());
return;
}
}
Expand Down
Loading