Sort inputs by amount in CoinJoin
MODIFY
WalletWasabi.Tests/RegTests.cs
WalletWasabi.Tests/RegTests.cs
@@ -2821,6 +2821,7 @@ namespace WalletWasabi.Tests
await rpc.GenerateAsync(100); // So to make sure we have enough money.
Uri baseUri = new Uri(RegTestFixture.BackendEndPoint);
+ var spentCoins = new List<Coin>();
var fundingTxCount = 0;
var inputRegistrationUsers = new List<(Requester requester, uint256 blinded, BitcoinAddress activeOutputAddress, BitcoinAddress changeOutputAddress, IEnumerable<InputProofModel> inputProofModels, List<(Key key, BitcoinWitPubKeyAddress address, uint256 txHash, Transaction tx, OutPoint input)> userInputData)>();
for (int i = 0; i < roundConfig.AnonymitySet; i++)
@@ -2852,6 +2853,7 @@ namespace WalletWasabi.Tests
Transaction transaction = await rpc.GetRawTransactionAsync(txHash);
var coin = transaction.Outputs.GetCoins(inputAddress.ScriptPubKey).Single();
+ spentCoins.Add(coin);
OutPoint input = coin.Outpoint;
var inputProof = new InputProofModel { Input = input.ToTxoRef(), Proof = key.SignCompact(blindedOutputScriptsHash) };
@@ -2980,9 +2982,13 @@ namespace WalletWasabi.Tests
var myDic = new Dictionary<int, WitScript>();
+ long previousAmount = -1;
for (int i = 0; i < unsignedCoinJoin.Inputs.Count; i++)
{
var input = unsignedCoinJoin.Inputs[i];
+ long currentAmount = spentCoins.Single(x => x.Outpoint == unsignedCoinJoin.Inputs[i].PrevOut).Amount;
+ Assert.True(previousAmount <= currentAmount);
+ previousAmount = currentAmount;
if (user.userInputData.Select(x => x.input).Contains(input.PrevOut))
{
myDic.Add(i, partSignedCj.Inputs[i].WitScript);

MODIFY
WalletWasabi/Extensions/NBitcoinExtensions.cs
WalletWasabi/Extensions/NBitcoinExtensions.cs
@@ -263,5 +263,15 @@ namespace NBitcoin
{
list.Sort((x, y) => x.Value.CompareTo(y.Value));
}
+
+ public static void SortByAmount(this TxInList list, List<Coin> coins)
+ {
+ var map = new Dictionary<TxIn, Coin>();
+ foreach (var coin in coins)
+ {
+ map.Add(list.Single(x => x.PrevOut == coin.Outpoint), coin);
+ }
+ list.Sort((x, y) => map[x].Amount.CompareTo(map[y].Amount));
+ }
}
}

MODIFY
WalletWasabi/Models/ChaumianCoinJoin/CcjRound.cs
WalletWasabi/Models/ChaumianCoinJoin/CcjRound.cs
@@ -411,7 +411,11 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
// 9. Shuffle.
UnsignedCoinJoin.Inputs.Shuffle();
UnsignedCoinJoin.Outputs.Shuffle();
- UnsignedCoinJoin.Outputs.SortByAmount(); // So the coinjoin looks better in block explorer.
+
+ // 10. Sort inputs and outputs by amount so the coinjoin looks better in a block explorer.
+ UnsignedCoinJoin.Inputs.SortByAmount(spentCoins);
+ UnsignedCoinJoin.Outputs.SortByAmount();
+ //Note: We shuffle then sort because inputs and outputs could have equal values
SignedCoinJoin = Transaction.Parse(UnsignedCoinJoin.ToHex(), Network);

Sort inputs by amount in CoinJoin