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

Sort inputs by amount in CoinJoin #1944

Merged
merged 1 commit into from Jul 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions WalletWasabi.Tests/RegTests.cs
Expand Up @@ -2821,6 +2821,7 @@ public async Task Ccj100ParticipantsTestsAsync()
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++)
Expand Down Expand Up @@ -2852,6 +2853,7 @@ public async Task Ccj100ParticipantsTestsAsync()
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) };
Expand Down Expand Up @@ -2980,9 +2982,13 @@ public async Task Ccj100ParticipantsTestsAsync()

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);
Expand Down
10 changes: 10 additions & 0 deletions WalletWasabi/Extensions/NBitcoinExtensions.cs
Expand Up @@ -263,5 +263,15 @@ public static void SortByAmount(this TxOutList list)
{
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));
}
benthecarman marked this conversation as resolved.
Show resolved Hide resolved
}
}
6 changes: 5 additions & 1 deletion WalletWasabi/Models/ChaumianCoinJoin/CcjRound.cs
Expand Up @@ -411,7 +411,11 @@ public async Task ExecuteNextPhaseAsync(CcjRoundPhase expectedPhase, Money feePe
// 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);

Expand Down