private async Task <bool> TryConfirmConnectionAsync(IEnumerable <long> amountsToRequest, IEnumerable <long> vsizesToRequest, CancellationToken cancellationToken) { var inputVsize = Coin.ScriptPubKey.EstimateInputVsize(); var totalFeeToPay = FeeRate.GetFee(Coin.ScriptPubKey.EstimateInputVsize()); var totalAmount = Coin.Amount; var effectiveAmount = totalAmount - totalFeeToPay; if (effectiveAmount <= Money.Zero) { throw new InvalidOperationException($"Round({ RoundId }), Alice({ AliceId}): Adding this input is uneconomical."); } var response = await ArenaClient .ConfirmConnectionAsync( RoundId, AliceId, amountsToRequest, vsizesToRequest, IssuedAmountCredentials, IssuedVsizeCredentials, cancellationToken) .ConfigureAwait(false); IssuedAmountCredentials = response.IssuedAmountCredentials; IssuedVsizeCredentials = response.IssuedVsizeCredentials; var isConfirmed = response.Value; return(isConfirmed); }
private async Task <bool> ConfirmConnectionAsync() { var inputWeight = 4 * Constants.P2wpkhInputVirtualSize; var inputRemainingWeights = new[] { (long)ArenaClient.ProtocolMaxWeightPerAlice - Coins.Count() * inputWeight }; var amountCredentials = ArenaClient.AmountCredentialClient.Credentials; var totalFeeToPay = FeeRate.GetFee(Coins.Sum(c => c.ScriptPubKey.EstimateInputVsize())); var totalAmount = Coins.Sum(coin => coin.Amount); if (totalFeeToPay > totalAmount) { throw new InvalidOperationException($"Round({ RoundId }), Alice({ AliceId}): Not enough funds to pay for the fees."); } var amountsToRequest = new[] { totalAmount - totalFeeToPay }; return(await ArenaClient .ConfirmConnectionAsync( RoundId, AliceId, inputRemainingWeights, amountCredentials.ZeroValue.Take(ArenaClient.ProtocolCredentialNumber), amountsToRequest) .ConfigureAwait(false)); }
public AliceClient(Guid aliceId, Guid roundId, ArenaClient arenaClient, IEnumerable <Coin> coins, FeeRate feeRate) { AliceId = aliceId; RoundId = roundId; ArenaClient = arenaClient; Coins = coins; FeeRate = feeRate; }
public AliceClient(uint256 roundId, ArenaClient arenaClient, Coin coin, FeeRate feeRate, BitcoinSecret bitcoinSecret) { AliceId = CalculateHash(coin, bitcoinSecret, roundId); RoundId = roundId; ArenaClient = arenaClient; Coin = coin; FeeRate = feeRate; BitcoinSecret = bitcoinSecret; RealAmountCredentials = Array.Empty <Credential>(); RealVsizeCredentials = Array.Empty <Credential>(); }
public async Task RegisterInputAsync(CancellationToken cancellationToken) { var response = await ArenaClient.RegisterInputAsync(RoundId, Coin.Outpoint, BitcoinSecret.PrivateKey, cancellationToken).ConfigureAwait(false); var remoteAliceId = response.Value; if (AliceId != remoteAliceId) { throw new InvalidOperationException($"Round ({RoundId}), Local Alice ({AliceId}) was computed as {remoteAliceId}"); } RealAmountCredentials = response.RealAmountCredentials; RealVsizeCredentials = response.RealVsizeCredentials; Logger.LogInfo($"Round ({RoundId}), Alice ({AliceId}): Registered an input."); }
public static async Task <AliceClient> CreateRegisterAndConfirmInputAsync( RoundState roundState, ArenaClient arenaClient, SmartCoin coin, BitcoinSecret bitcoinSecret, RoundStateUpdater roundStatusUpdater, CancellationToken cancellationToken) { AliceClient?aliceClient = null; try { aliceClient = await RegisterInputAsync(roundState, arenaClient, coin, bitcoinSecret, cancellationToken).ConfigureAwait(false); await aliceClient.ConfirmConnectionAsync(roundStatusUpdater, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { if (aliceClient is { })
public static async Task <AliceClient> CreateNewAsync( ArenaClient arenaClient, IEnumerable <Coin> coinsToRegister, BitcoinSecret bitcoinSecret, Guid roundId, uint256 roundHash, FeeRate feeRate) { IEnumerable <Money> amounts = coinsToRegister.Select(c => c.Amount); IEnumerable <OutPoint> outPoints = coinsToRegister.Select(c => c.Outpoint); IEnumerable <Key> keys = Enumerable.Repeat(bitcoinSecret.PrivateKey, coinsToRegister.Count()); Guid aliceId = await arenaClient.RegisterInputAsync(amounts, outPoints, keys, roundId, roundHash).ConfigureAwait(false); AliceClient client = new(aliceId, roundId, arenaClient, coinsToRegister, feeRate); Logger.LogInfo($"Round ({roundId}), Alice ({aliceId}): Registered {amounts.Count()} inputs."); return(client); }
private AliceClient( Guid aliceId, RoundState roundState, ArenaClient arenaClient, SmartCoin coin, BitcoinSecret bitcoinSecret, IEnumerable <Credential> issuedAmountCredentials, IEnumerable <Credential> issuedVsizeCredentials) { AliceId = aliceId; RoundId = roundState.Id; ArenaClient = arenaClient; SmartCoin = coin; FeeRate = roundState.FeeRate; BitcoinSecret = bitcoinSecret; IssuedAmountCredentials = issuedAmountCredentials; IssuedVsizeCredentials = issuedVsizeCredentials; MaxVsizeAllocationPerAlice = roundState.MaxVsizeAllocationPerAlice; ConfirmationTimeout = roundState.ConnectionConfirmationTimeout / 2; }
public static async Task <AliceClient> CreateRegisterAndConfirmInputAsync( RoundState roundState, ArenaClient arenaClient, SmartCoin coin, BitcoinSecret bitcoinSecret, Key identificationKey, RoundStateUpdater roundStatusUpdater, CancellationToken cancellationToken) { AliceClient?aliceClient = null; try { aliceClient = await RegisterInputAsync(roundState, arenaClient, coin, bitcoinSecret, identificationKey, cancellationToken).ConfigureAwait(false); await aliceClient.ConfirmConnectionAsync(roundStatusUpdater, cancellationToken).ConfigureAwait(false); Logger.LogInfo($"Round ({aliceClient.RoundId}), Alice ({aliceClient.AliceId}): Connection successfully confirmed."); } catch (OperationCanceledException) { if (aliceClient is { })
private async Task <bool> TryConfirmConnectionAsync(long vsizeAllocationToRequest, CancellationToken cancellationToken) { var inputVsize = Coin.ScriptPubKey.EstimateInputVsize(); var vsizesToRequest = new[] { vsizeAllocationToRequest - inputVsize }; var totalFeeToPay = FeeRate.GetFee(Coin.ScriptPubKey.EstimateInputVsize()); var totalAmount = Coin.Amount; var effectiveAmount = totalAmount - totalFeeToPay; if (effectiveAmount <= Money.Zero) { throw new InvalidOperationException($"Round({ RoundId }), Alice({ AliceId}): Not enough funds to pay for the fees."); } var amountsToRequest = new[] { effectiveAmount.Satoshi }; var response = await ArenaClient .ConfirmConnectionAsync( RoundId, AliceId, amountsToRequest, vsizesToRequest, RealAmountCredentials, RealVsizeCredentials, cancellationToken) .ConfigureAwait(false); var isConfirmed = response.Value; if (isConfirmed) { RealAmountCredentials = response.RealAmountCredentials; RealVsizeCredentials = response.RealVsizeCredentials; } return(isConfirmed); }
public BobClient(uint256 roundId, ArenaClient arenaClient) { RoundId = roundId; ArenaClient = arenaClient; }
public BobClient(Guid roundId, ArenaClient arenaClient) { RoundId = roundId; ArenaClient = arenaClient; }
public async Task SignTransactionAsync(BitcoinSecret bitcoinSecret, Transaction unsignedCoinJoin) { await ArenaClient.SignTransactionAsync(RoundId, Coins, bitcoinSecret, unsignedCoinJoin).ConfigureAwait(false); Logger.LogInfo($"Round ({RoundId}), Alice ({AliceId}): Posted {Coins.Count()} signatures."); }
public async Task RemoveInputAsync() { await ArenaClient.RemoveInputAsync(RoundId, AliceId).ConfigureAwait(false); Logger.LogInfo($"Round ({RoundId}), Alice ({AliceId}): Inputs removed."); }
public async Task SignTransactionAsync(Transaction unsignedCoinJoin, CancellationToken cancellationToken) { await ArenaClient.SignTransactionAsync(RoundId, Coin, BitcoinSecret, unsignedCoinJoin, cancellationToken).ConfigureAwait(false); Logger.LogInfo($"Round ({RoundId}), Alice ({AliceId}): Posted a signature."); }
public async Task ReadyToSignAsync(CancellationToken cancellationToken) { await ArenaClient.ReadyToSignAsync(RoundId, AliceId, BitcoinSecret.PrivateKey, cancellationToken).ConfigureAwait(false); Logger.LogInfo($"Round ({RoundId}), Alice ({AliceId}): Ready to sign."); }