Skip to content

Commit

Permalink
Simplify denominations building (WalletWasabi#13326)
Browse files Browse the repository at this point in the history
  • Loading branch information
lontivero authored Aug 19, 2024
1 parent aea13da commit 73b623d
Showing 1 changed file with 22 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,123 +15,27 @@ public static IOrderedEnumerable<Output> CreateDenominations(
IEnumerable<ScriptType> allowedOutputTypes,
WasabiRandom random)
{
var denominations = new HashSet<Output>();

Output CreateDenom(double sats)
{
var scriptType = allowedOutputTypes.RandomElement(random);
return Output.FromDenomination(Money.Satoshis((ulong)sats), scriptType, feeRate);
}

// Powers of 2
for (int i = 0; i < int.MaxValue; i++)
{
var denom = CreateDenom(Math.Pow(2, i));

if (denom.Amount < minAllowedOutputAmount)
{
continue;
}

if (denom.Amount > maxAllowedOutputAmount)
{
break;
}

denominations.Add(denom);
}

// Powers of 3
for (int i = 0; i < int.MaxValue; i++)
{
var denom = CreateDenom(Math.Pow(3, i));

if (denom.Amount < minAllowedOutputAmount)
{
continue;
}

if (denom.Amount > maxAllowedOutputAmount)
{
break;
}

denominations.Add(denom);
}

// Powers of 3 * 2
for (int i = 0; i < int.MaxValue; i++)
{
var denom = CreateDenom(Math.Pow(3, i) * 2);

if (denom.Amount < minAllowedOutputAmount)
{
continue;
}

if (denom.Amount > maxAllowedOutputAmount)
{
break;
}

denominations.Add(denom);
}

// Powers of 10 (1-2-5 series)
for (int i = 0; i < int.MaxValue; i++)
{
var denom = CreateDenom(Math.Pow(10, i));

if (denom.Amount < minAllowedOutputAmount)
{
continue;
}

if (denom.Amount > maxAllowedOutputAmount)
{
break;
}

denominations.Add(denom);
}

// Powers of 10 * 2 (1-2-5 series)
for (int i = 0; i < int.MaxValue; i++)
{
var denom = CreateDenom(Math.Pow(10, i) * 2);

if (denom.Amount < minAllowedOutputAmount)
{
continue;
}

if (denom.Amount > maxAllowedOutputAmount)
{
break;
}

denominations.Add(denom);
}

// Powers of 10 * 5 (1-2-5 series)
for (int i = 0; i < int.MaxValue; i++)
{
var denom = CreateDenom(Math.Pow(10, i) * 5);

if (denom.Amount < minAllowedOutputAmount)
{
continue;
}

if (denom.Amount > maxAllowedOutputAmount)
{
break;
}

denominations.Add(denom);
}

// Greedy decomposer will take the higher values first. Order in a way to prioritize cheaper denominations, this only matters in case of equality.
return denominations.OrderByDescending(x => x.EffectiveAmount);
Output CreateDenom(decimal sats) =>
Output.FromDenomination(Money.Satoshis((ulong)sats), allowedOutputTypes.RandomElement(random), feeRate);

IEnumerable<decimal> Times(int times, IEnumerable<decimal> values) =>
values
.Select(value => times * value)
.SkipWhile(denom => denom < minAllowedOutputAmount.Satoshi)
.TakeWhile(denom => denom <= maxAllowedOutputAmount.Satoshi);

IEnumerable<decimal> PowersOf(double baseValue) =>
Enumerable.Range(0, short.MaxValue)
.Select(i => (decimal)Math.Pow(baseValue, i));

return Times(1, PowersOf(2))
.Concat(Times(1, PowersOf(3)))
.Concat(Times(2, PowersOf(3)))
.Concat(Times(1, PowersOf(10)))
.Concat(Times(2, PowersOf(10)))
.Concat(Times(5, PowersOf(10)))
.ToHashSet()
.Select(CreateDenom)
.OrderByDescending(x => x.EffectiveAmount);
}
}

0 comments on commit 73b623d

Please sign in to comment.