Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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));
        }
Ejemplo n.º 3
0
 public AliceClient(Guid aliceId, Guid roundId, ArenaClient arenaClient, IEnumerable <Coin> coins, FeeRate feeRate)
 {
     AliceId     = aliceId;
     RoundId     = roundId;
     ArenaClient = arenaClient;
     Coins       = coins;
     FeeRate     = feeRate;
 }
Ejemplo n.º 4
0
 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>();
 }
Ejemplo n.º 5
0
        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.");
        }
Ejemplo n.º 6
0
        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 { })
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
 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;
 }
Ejemplo n.º 9
0
        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 { })
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
 public BobClient(uint256 roundId, ArenaClient arenaClient)
 {
     RoundId     = roundId;
     ArenaClient = arenaClient;
 }
Ejemplo n.º 12
0
 public BobClient(Guid roundId, ArenaClient arenaClient)
 {
     RoundId     = roundId;
     ArenaClient = arenaClient;
 }
Ejemplo n.º 13
0
        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.");
        }
Ejemplo n.º 14
0
        public async Task RemoveInputAsync()
        {
            await ArenaClient.RemoveInputAsync(RoundId, AliceId).ConfigureAwait(false);

            Logger.LogInfo($"Round ({RoundId}), Alice ({AliceId}): Inputs removed.");
        }
Ejemplo n.º 15
0
        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.");
        }
Ejemplo n.º 16
0
        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.");
        }