Skip to content
Permalink
Browse files

Don't try to reregister banned coins when other coins are queued

  • Loading branch information...
nopara73 committed Nov 14, 2018
1 parent 5ecae35 commit 0beb4a67a9144e9cc37cc988d6f37d48faa339b8
@@ -129,8 +129,10 @@ public void SmartCoinSerialization()
var spentOutputs = tx.Inputs.ToTxoRefs().ToArray();
var height = Height.MemPool;
var label = "foo";
var bannedUntil = DateTimeOffset.UtcNow;

var coin = new SmartCoin(txId, index, scriptPubKey, amount, spentOutputs, height, tx.RBF, tx.GetMixin(index), label, txId);
coin.BannedUntilUtc = bannedUntil;

var serialized = JsonConvert.SerializeObject(coin);
var deserialized = JsonConvert.DeserializeObject<SmartCoin>(serialized);
@@ -145,6 +147,7 @@ public void SmartCoinSerialization()
Assert.Equal(coin.SpenderTransactionId, deserialized.SpenderTransactionId);
Assert.Equal(coin.TransactionId, deserialized.TransactionId);
Assert.Equal(coin.SpentOutputs.Length, deserialized.SpentOutputs.Length);
Assert.Equal(coin.BannedUntilUtc, deserialized.BannedUntilUtc);
for (int i = 0; i < coin.SpentOutputs.Length; i++)
{
Assert.Equal(coin.SpentOutputs[0], deserialized.SpentOutputs[0]);
@@ -183,10 +183,12 @@ public IEnumerable<(uint256 txid, uint index)> GetRegistrableCoins(int maximumIn
var amountSoFar = Money.Zero;
Money amountNeededExceptInputFees = denomination + (feePerOutputs * 2);
foreach (SmartCoin coin in WaitingList
.Where(y => y.Value <= DateTimeOffset.UtcNow).Select(z => z.Key) // Only if registering coins is already allowed.
.Where(x => x.Confirmed || x.Label.StartsWith("ZeroLink", StringComparison.Ordinal)) // Where our label contains CoinJoin, CoinJoins can be registered even if not confirmed, our label will likely be CoinJoin only if it was a previous CoinJoin, otherwise the server will refuse us.
.OrderByDescending(y => y.Amount) // First order by amount.
.ThenByDescending(z => z.Confirmed)) // Then order by the amount ordered ienumerable by confirmation, so first try to register confirmed coins.
.Where(x => x.Value <= DateTimeOffset.UtcNow)
.Select(x => x.Key) // Only if registering coins is already allowed.
.Where(x => x.Confirmed || x.Label.StartsWith("ZeroLink", StringComparison.Ordinal)) // Where our label contains CoinJoin, CoinJoins can be registered even if not confirmed, our label will likely be CoinJoin only if it was a previous CoinJoin, otherwise the server will refuse us.
.OrderBy(x => x.IsBanned) // First order non-banned coins to first.
.ThenByDescending(x => x.Amount) // Then order by amount.
.ThenByDescending(x => x.Confirmed)) // Then order by the amount ordered ienumerable by confirmation, so first try to register confirmed coins.
{
coinsToRegister.Add(coin);

@@ -132,9 +132,13 @@ public bool CoinJoinInProgress
[JsonProperty(Order = 11)]
public int Mixin { get; }

[JsonProperty(Order = 12)]
public DateTimeOffset? BannedUntilUtc { get; set; }

public bool SpentOrCoinJoinInProgress => !(SpenderTransactionId is null) || CoinJoinInProgress;
public bool Unspent => SpenderTransactionId is null;
public bool Confirmed => Height != Height.MemPool && Height != Height.Unknown;
public bool IsBanned => BannedUntilUtc != null && BannedUntilUtc > DateTimeOffset.UtcNow;

/// <summary>
/// Mixin + 1
@@ -161,6 +165,7 @@ public SmartCoin(uint256 transactionId, uint index, Script scriptPubKey, Money a
RBF = rbf;
CoinJoinInProgress = coinJoinInProgress;
Secret = null;
BannedUntilUtc = null;
}

public SmartCoin(Coin coin, TxoRef[] spentOutputs, Height height, bool rbf, int mixin, string label = "", uint256 spenderTransactionId = null, bool coinJoinInProgress = false)
@@ -502,7 +502,27 @@ private async Task TryRegisterCoinsAsync(CcjClientRound inputRegistrableRound)
};
inputProofs.Add(inputProof);
}
AliceClient aliceClient = await AliceClient.CreateNewAsync(Network, changeAddress, blind.BlindedData, inputProofs, CcjHostUri, TorSocks5EndPoint);

AliceClient aliceClient = null;
try
{
aliceClient = await AliceClient.CreateNewAsync(Network, changeAddress, blind.BlindedData, inputProofs, CcjHostUri, TorSocks5EndPoint);
}
catch (HttpRequestException ex) when (ex.Message.Contains("Input is banned", StringComparison.InvariantCultureIgnoreCase))
{
string[] parts = ex.Message.Split(new[] { "Input is banned from participation for ", " minutes: " }, StringSplitOptions.RemoveEmptyEntries);
string minutesString = parts[1];
int minuteInt = int.Parse(minutesString);
string bannedInputString = parts[2].TrimEnd('.');
string[] bannedInputStringParts = bannedInputString.Split(':', StringSplitOptions.RemoveEmptyEntries);
(uint256 txid, uint index) coinReference = (new uint256(bannedInputStringParts[1]), uint.Parse(bannedInputStringParts[0]));
SmartCoin coin = State.GetSingleOrDefaultFromWaitingList(coinReference);
if (coin is null) throw new NotSupportedException("This is impossible.");
coin.BannedUntilUtc = DateTimeOffset.UtcNow + TimeSpan.FromMinutes(minuteInt);

Logger.LogWarning<CcjClient>(ex.Message.Split('\n')[1]);
return;
}

byte[] unblindedSignature = CoordinatorPubKey.UnblindSignature(aliceClient.BlindedOutputSignature, blind.BlindingFactor);

0 comments on commit 0beb4a6

Please sign in to comment.
You can’t perform that action at this time.