CreateRoundWithTwoConfirmedConnectionsAsync(Arena arena, Key key1, Coin coin1, Key key2, Coin coin2)
        {
            // Create the round.
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            var arenaClient = WabiSabiFactory.CreateArenaClient(arena);
            var round       = Assert.Single(arena.Rounds);

            // Register Alices.
            var aliceClient1 = new AliceClient(round.Id, arenaClient, coin1, round.FeeRate, key1.GetBitcoinSecret(round.Network));
            var aliceClient2 = new AliceClient(round.Id, arenaClient, coin2, round.FeeRate, key2.GetBitcoinSecret(round.Network));

            await aliceClient1.RegisterInputAsync(CancellationToken.None).ConfigureAwait(false);

            await aliceClient2.RegisterInputAsync(CancellationToken.None).ConfigureAwait(false);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.ConnectionConfirmation, round.Phase);

            // Confirm connections.
            await aliceClient1.ConfirmConnectionAsync(TimeSpan.FromSeconds(1), round.MaxVsizeAllocationPerAlice, CancellationToken.None).ConfigureAwait(false);

            await aliceClient2.ConfirmConnectionAsync(TimeSpan.FromSeconds(1), round.MaxVsizeAllocationPerAlice, CancellationToken.None).ConfigureAwait(false);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.OutputRegistration, round.Phase);

            return(round,
                   arenaClient,
                   new[]
示例#2
0
        public async Task AliceTimesoutAsync()
        {
            // Alice times out when its deadline is reached.
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

            using Key key = new();
            var coin = WabiSabiFactory.CreateCoin(key);
            var rpc  = WabiSabiFactory.CreatePreconfiguredRpcClient(coin);

            using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, rpc, round);

            var arenaClient = WabiSabiFactory.CreateArenaClient(arena);

            // Register Alices.
            var minAliceDeadline = DateTimeOffset.UtcNow + cfg.ConnectionConfirmationTimeout * 0.9;
            var aliceClient      = new AliceClient(round.Id, arenaClient, coin, round.FeeRate, key.GetBitcoinSecret(round.Network));
            await aliceClient.RegisterInputAsync(CancellationToken.None).ConfigureAwait(false);

            var alice = Assert.Single(round.Alices);

            alice.Deadline = DateTimeOffset.UtcNow - TimeSpan.FromMilliseconds(1);
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Empty(round.Alices);

            await arena.StopAsync(CancellationToken.None);
        }
示例#3
0
        CreateRoundWithOutputsReadyToSignAsync(Arena arena, Key key1, Coin coin1, Key key2, Coin coin2)
        {
            // Create the round.
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            var round       = Assert.Single(arena.Rounds);
            var arenaClient = WabiSabiFactory.CreateArenaClient(arena);

            // Register Alices.
            var aliceClient1 = new AliceClient(round.Id, arenaClient, coin1, round.FeeRate, key1.GetBitcoinSecret(round.Network));
            var aliceClient2 = new AliceClient(round.Id, arenaClient, coin2, round.FeeRate, key2.GetBitcoinSecret(round.Network));

            await aliceClient1.RegisterInputAsync(CancellationToken.None).ConfigureAwait(false);

            await aliceClient2.RegisterInputAsync(CancellationToken.None).ConfigureAwait(false);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.ConnectionConfirmation, round.Phase);

            // Confirm connections.
            await aliceClient1.ConfirmConnectionAsync(TimeSpan.FromMilliseconds(100), round.MaxVsizeAllocationPerAlice, CancellationToken.None).ConfigureAwait(false);

            await aliceClient2.ConfirmConnectionAsync(TimeSpan.FromMilliseconds(100), round.MaxVsizeAllocationPerAlice, CancellationToken.None).ConfigureAwait(false);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.OutputRegistration, round.Phase);

            // Register outputs.
            var bobClient = new BobClient(round.Id, arenaClient);

            using var destKey1 = new Key();
            using var destKey2 = new Key();
            await bobClient.RegisterOutputAsync(
                coin1.Amount - round.FeeRate.GetFee(coin1.ScriptPubKey.EstimateInputVsize()),
                destKey1.PubKey.WitHash.ScriptPubKey,
                aliceClient1.RealAmountCredentials,
                aliceClient1.RealVsizeCredentials,
                CancellationToken.None).ConfigureAwait(false);

            await bobClient.RegisterOutputAsync(
                coin2.Amount - round.FeeRate.GetFee(coin2.ScriptPubKey.EstimateInputVsize()),
                destKey1.PubKey.WitHash.ScriptPubKey,
                aliceClient2.RealAmountCredentials,
                aliceClient2.RealVsizeCredentials,
                CancellationToken.None).ConfigureAwait(false);

            return(round, aliceClient1, aliceClient2);
        }
        CreateRoundWithTwoConfirmedConnectionsAsync(Arena arena, Key key1, Coin coin1, Key key2, Coin coin2)
        {
            // Create the round.
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            var arenaClient = WabiSabiFactory.CreateArenaClient(arena);
            var round       = Assert.Single(arena.Rounds);

            // Register Alices.
            var aliceClient1 = new AliceClient(round.Id, arenaClient, coin1, round.FeeRate, key1.GetBitcoinSecret(round.Network));
            var aliceClient2 = new AliceClient(round.Id, arenaClient, coin2, round.FeeRate, key2.GetBitcoinSecret(round.Network));

            await aliceClient1.RegisterInputAsync(CancellationToken.None).ConfigureAwait(false);

            await aliceClient2.RegisterInputAsync(CancellationToken.None).ConfigureAwait(false);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.ConnectionConfirmation, round.Phase);

            // Confirm connections.
            using RoundStateUpdater roundStateUpdater = new(TimeSpan.FromSeconds(2), new ArenaRequestHandlerAdapter(arena));
            await aliceClient1.ConfirmConnectionAsync(
                TimeSpan.FromSeconds(1),
                new long[] { coin1.EffectiveValue(round.FeeRate) },
                new long[] { round.MaxVsizeAllocationPerAlice - coin1.ScriptPubKey.EstimateInputVsize() },
                roundStateUpdater,
                CancellationToken.None).ConfigureAwait(false);

            await aliceClient2.ConfirmConnectionAsync(
                TimeSpan.FromSeconds(1),
                new long[] { coin2.EffectiveValue(round.FeeRate) },
                new long[] { round.MaxVsizeAllocationPerAlice - coin2.ScriptPubKey.EstimateInputVsize() },
                roundStateUpdater,
                CancellationToken.None).ConfigureAwait(false);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.OutputRegistration, round.Phase);

            return(round,
                   arenaClient,
                   new[]
            {
                aliceClient1,
                aliceClient2
            });
        }
示例#5
0
        public async Task CreateNewAsync()
        {
            var config = new WabiSabiConfig {
                MaxInputCountByRound = 1
            };
            var       round = WabiSabiFactory.CreateRound(config);
            var       km    = ServiceFactory.CreateKeyManager("");
            var       key   = BitcoinFactory.CreateHdPubKey(km);
            SmartCoin coin1 = BitcoinFactory.CreateSmartCoin(key, Money.Coins(1m));

            var mockRpc = WabiSabiFactory.CreatePreconfiguredRpcClient(coin1.Coin);

            using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(config, mockRpc, round);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromMinutes(1));

            await using var coordinator = new ArenaRequestHandler(config, new Prison(), arena, mockRpc.Object);
            var wabiSabiApi = new WabiSabiController(coordinator);

            var insecureRandom = new InsecureRandom();
            var roundState     = RoundState.FromRound(round);
            var arenaClient    = new ArenaClient(
                roundState.CreateAmountCredentialClient(insecureRandom),
                roundState.CreateVsizeCredentialClient(insecureRandom),
                wabiSabiApi);

            Assert.Equal(Phase.InputRegistration, arena.Rounds.First().Phase);

            var bitcoinSecret = km.GetSecrets("", coin1.ScriptPubKey).Single().PrivateKey.GetBitcoinSecret(Network.Main);

            var aliceClient = new AliceClient(round.Id, arenaClient, coin1.Coin, round.FeeRate, bitcoinSecret);
            await aliceClient.RegisterInputAsync(CancellationToken.None);

            using RoundStateUpdater roundStateUpdater = new(TimeSpan.FromSeconds(2), wabiSabiApi);
            Task confirmationTask = aliceClient.ConfirmConnectionAsync(
                TimeSpan.FromSeconds(1),
                new long[] { coin1.EffectiveValue(round.FeeRate) },
                new long[] { roundState.MaxVsizeAllocationPerAlice - coin1.ScriptPubKey.EstimateInputVsize() },
                roundStateUpdater,
                CancellationToken.None);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromMinutes(1));

            await confirmationTask;

            Assert.Equal(Phase.ConnectionConfirmation, arena.Rounds.First().Phase);
        }
        CreateRoundWithOutputsReadyToSignAsync(Arena arena, Key key1, Coin coin1, Key key2, Coin coin2)
        {
            // Create the round.
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            var round       = Assert.Single(arena.Rounds);
            var arenaClient = WabiSabiFactory.CreateArenaClient(arena);

            // Register Alices.
            var aliceClient1 = new AliceClient(round.Id, arenaClient, coin1, round.FeeRate, key1.GetBitcoinSecret(round.Network));
            var aliceClient2 = new AliceClient(round.Id, arenaClient, coin2, round.FeeRate, key2.GetBitcoinSecret(round.Network));

            await aliceClient1.RegisterInputAsync(CancellationToken.None).ConfigureAwait(false);

            await aliceClient2.RegisterInputAsync(CancellationToken.None).ConfigureAwait(false);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.ConnectionConfirmation, round.Phase);

            // Confirm connections.
            using RoundStateUpdater roundStateUpdater = new(TimeSpan.FromSeconds(2), new ArenaRequestHandlerAdapter(arena));
            await aliceClient1.ConfirmConnectionAsync(
                TimeSpan.FromMilliseconds(100),
                new long[] { coin1.EffectiveValue(round.FeeRate) },
                new long[] { round.MaxVsizeAllocationPerAlice - coin1.ScriptPubKey.EstimateInputVsize() },
                roundStateUpdater,
                CancellationToken.None).ConfigureAwait(false);

            await aliceClient2.ConfirmConnectionAsync(
                TimeSpan.FromMilliseconds(100),
                new long[] { coin2.EffectiveValue(round.FeeRate) },
                new long[] { round.MaxVsizeAllocationPerAlice - coin2.ScriptPubKey.EstimateInputVsize() },
                roundStateUpdater,
                CancellationToken.None).ConfigureAwait(false);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.OutputRegistration, round.Phase);

            // Register outputs.
            var bobClient = new BobClient(round.Id, arenaClient);

            using var destKey1 = new Key();
            using var destKey2 = new Key();
            await bobClient.RegisterOutputAsync(
                coin1.Amount - round.FeeRate.GetFee(coin1.ScriptPubKey.EstimateInputVsize()),
                destKey1.PubKey.WitHash.ScriptPubKey,
                aliceClient1.IssuedAmountCredentials.Take(ProtocolConstants.CredentialNumber),
                aliceClient1.IssuedVsizeCredentials.Take(ProtocolConstants.CredentialNumber),
                CancellationToken.None).ConfigureAwait(false);

            await bobClient.RegisterOutputAsync(
                coin2.Amount - round.FeeRate.GetFee(coin2.ScriptPubKey.EstimateInputVsize()),
                destKey1.PubKey.WitHash.ScriptPubKey,
                aliceClient2.IssuedAmountCredentials.Take(ProtocolConstants.CredentialNumber),
                aliceClient2.IssuedVsizeCredentials.Take(ProtocolConstants.CredentialNumber),
                CancellationToken.None).ConfigureAwait(false);

            return(round, aliceClient1, aliceClient2);
        }
示例#7
0
        public async Task RegisterOutputTestAsync()
        {
            var config = new WabiSabiConfig {
                MaxInputCountByRound = 1
            };
            var       round = WabiSabiFactory.CreateRound(config);
            var       km    = ServiceFactory.CreateKeyManager("");
            var       key   = BitcoinFactory.CreateHdPubKey(km);
            SmartCoin coin1 = BitcoinFactory.CreateSmartCoin(key, Money.Coins(2m));

            var mockRpc = WabiSabiFactory.CreatePreconfiguredRpcClient(coin1.Coin);

            using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(config, mockRpc, round);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromMinutes(1));

            ZeroCredentialPool zeroAmountCredential = new();
            ZeroCredentialPool zeroVsizeCredential  = new();

            await using var coordinator = new ArenaRequestHandler(config, new Prison(), arena, mockRpc.Object);
            var insecureRandom   = new InsecureRandom();
            var wabiSabiApi      = new WabiSabiController(coordinator);
            var roundState       = RoundState.FromRound(round);
            var aliceArenaClient = new ArenaClient(
                roundState.CreateAmountCredentialClient(zeroAmountCredential, insecureRandom),
                roundState.CreateVsizeCredentialClient(zeroVsizeCredential, insecureRandom),
                wabiSabiApi);
            var bobArenaClient = new ArenaClient(
                roundState.CreateAmountCredentialClient(zeroAmountCredential, insecureRandom),
                roundState.CreateVsizeCredentialClient(zeroVsizeCredential, insecureRandom),
                wabiSabiApi);

            Assert.Equal(Phase.InputRegistration, round.Phase);

            var bitcoinSecret = km.GetSecrets("", coin1.ScriptPubKey).Single().PrivateKey.GetBitcoinSecret(Network.Main);

            var aliceClient = new AliceClient(round.Id, aliceArenaClient, coin1.Coin, round.FeeRate, bitcoinSecret);
            await aliceClient.RegisterInputAsync(CancellationToken.None);

            Task confirmationTask = aliceClient.ConfirmConnectionAsync(TimeSpan.FromSeconds(1), roundState.MaxVsizeAllocationPerAlice, CancellationToken.None);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromMinutes(1));

            await confirmationTask;

            Assert.Equal(Phase.ConnectionConfirmation, round.Phase);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromMinutes(1));

            Assert.Equal(Phase.OutputRegistration, round.Phase);

            using var destinationKey = new Key();
            var destination = destinationKey.PubKey.WitHash.ScriptPubKey;

            var bobClient = new BobClient(round.Id, bobArenaClient);

            await bobClient.RegisterOutputAsync(Money.Coins(0.25m), destination, aliceClient.RealAmountCredentials, aliceClient.RealVsizeCredentials, CancellationToken.None);

            var bob = Assert.Single(round.Bobs);

            Assert.Equal(destination, bob.Script);
            Assert.Equal(25_000_000, bob.CredentialAmount);
        }