Пример #1
0
        public async Task TooMuchWeightAsync()
        {
            MockArena      arena = new();
            WabiSabiConfig cfg   = new() { MaxRegistrableWeight = 1 };
            var            round = WabiSabiFactory.CreateRound(cfg);

            arena.OnTryGetRound = _ => round;
            MockRpcClient rpc = new();

            using Key key = new();

            rpc.OnGetTxOutAsync = (_, _, _) => new()
            {
                Confirmations    = 1,
                ScriptPubKeyType = "witness_v0_keyhash",
                TxOut            = new TxOut(Money.Coins(1), key.PubKey.GetSegwitAddress(Network.Main))
            };

            await using PostRequestHandler handler = new(cfg, new Prison(), arena, rpc);
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.TooMuchWeight, ex.ErrorCode);
        }
    }
}
Пример #2
0
        public async Task ScriptNotAllowedAsync()
        {
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            MockRpcClient rpc = new();

            using Key key = new();

            rpc.OnGetTxOutAsync = (_, _, _) => new()
            {
                Confirmations = 1,
                TxOut         = new(Money.Coins(1), key.PubKey.GetScriptAddress(Network.Main))
            };

            await using ArenaRequestHandler handler = new(cfg, new(), arena, rpc);
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.ScriptNotAllowed, ex.ErrorCode);

            await arena.StopAsync(CancellationToken.None);
        }
Пример #3
0
        public async Task WrongPhaseAsync()
        {
            WabiSabiConfig cfg = new();

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

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

            var round = arena.Rounds.First().Value;

            using Key key = new();
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);

            await using ArenaRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));

            foreach (Phase phase in Enum.GetValues(typeof(Phase)))
            {
                if (phase != Phase.InputRegistration)
                {
                    round.SetPhase(phase);
                    await RegisterAndAssertWrongPhaseAsync(req, handler);
                }
            }

            await arena.StopAsync(CancellationToken.None);
        }
Пример #4
0
        public async Task AliceTimesoutAsync()
        {
            // Alice times out when its deadline is reached.
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            MockRpcClient rpc = new();

            using Key key = new();

            rpc.OnGetTxOutAsync = (_, _, _) => new()
            {
                Confirmations    = 1,
                ScriptPubKeyType = "witness_v0_keyhash",
                TxOut            = new TxOut(Money.Coins(1), key.PubKey.GetSegwitAddress(Network.Main))
            };

            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);

            await using PostRequestHandler handler = new(cfg, new Prison(), arena, rpc);
            var minAliceDeadline = DateTimeOffset.UtcNow + cfg.ConnectionConfirmationTimeout * 0.9;
            await handler.RegisterInputAsync(req);

            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);
        }
Пример #5
0
        public async Task InputRegistrationFullWeightAsync()
        {
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            using Key key = new();

            await using ArenaRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));

            // TODO add configuration parameter
            round.InitialInputVsizeAllocation = (int)round.PerAliceVsizeAllocation;

            // Add an alice
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            round.Alices.Add(WabiSabiFactory.CreateAlice());

            Assert.Equal(0, round.RemainingInputVsizeAllocation);

            // try to add an additional input
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.TooMuchTotalWeight, ex.ErrorCode);

            await arena.StopAsync(CancellationToken.None);
        }
        public async Task SuccessWithAliceUpdateCrossRoundAsync()
        {
            WabiSabiConfig cfg          = new();
            var            round        = WabiSabiFactory.CreateRound(cfg);
            var            anotherRound = WabiSabiFactory.CreateRound(cfg);

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

            using Key key = new();

            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);

            // Make sure an Alice have already been registered with the same input.
            var preAlice = WabiSabiFactory.CreateAlice(req.InputRoundSignaturePairs);

            anotherRound.Alices.Add(preAlice);

            await using ArenaRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));
            var minAliceDeadline = DateTimeOffset.UtcNow + cfg.ConnectionConfirmationTimeout * 0.9;
            var resp             = await handler.RegisterInputAsync(req);

            AssertSingleAliceSuccessfullyRegistered(round, minAliceDeadline, resp);
            Assert.Empty(anotherRound.Alices);

            await arena.StopAsync(CancellationToken.None);
        }
Пример #7
0
        public async Task AliceAlreadyRegisteredCrossRoundAsync()
        {
            WabiSabiConfig cfg          = new();
            var            round        = WabiSabiFactory.CreateRound(cfg);
            var            anotherRound = WabiSabiFactory.CreateRound(cfg);

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

            using Key key = new();

            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);

            // Make sure an Alice have already been registered with the same input.
            var preAlice = WabiSabiFactory.CreateAlice(req.InputRoundSignaturePairs);

            anotherRound.Alices.Add(preAlice);
            anotherRound.SetPhase(Phase.ConnectionConfirmation);

            await using ArenaRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));
            var ex = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.AliceAlreadyRegistered, ex.ErrorCode);

            await arena.StopAsync(CancellationToken.None);
        }
Пример #8
0
        public async Task RoundNotFoundAsync()
        {
            MockArena arena = new();

            arena.OnTryGetRound = _ => null;

            await using PostRequestHandler handler = new(new WabiSabiConfig(), new Prison(), arena, new MockRpcClient());
            var req = WabiSabiFactory.CreateInputsRegistrationRequest();
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.RoundNotFound, ex.ErrorCode);
        }
Пример #9
0
        public async Task RoundNotFoundAsync()
        {
            using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync();

            using Key key = new();

            await using ArenaRequestHandler handler = new(new(), new(), arena, WabiSabiFactory.CreateMockRpc(key));
            var req = WabiSabiFactory.CreateInputsRegistrationRequest();
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.RoundNotFound, ex.ErrorCode);

            await arena.StopAsync(CancellationToken.None);
        }
Пример #10
0
        public async Task TooManyInputsAsync()
        {
            MockArena      arena = new();
            WabiSabiConfig cfg   = new() { MaxInputCountByAlice = 3 };
            var            round = WabiSabiFactory.CreateRound(cfg);

            arena.OnTryGetRound = _ => round;

            await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(WabiSabiFactory.CreateInputRoundSignaturePairs(4), round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.TooManyInputs, ex.ErrorCode);
        }
Пример #11
0
        public async Task TooManyInputsAsync()
        {
            WabiSabiConfig cfg   = new() { MaxInputCountByAlice = 3 };
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            using Key key = new();

            await using ArenaRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(WabiSabiFactory.CreateInputRoundSignaturePairs(4), round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.TooManyInputs, ex.ErrorCode);

            await arena.StopAsync(CancellationToken.None);
        }
Пример #12
0
        public async Task NonUniqueInputsAsync()
        {
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            var inputSigPair = WabiSabiFactory.CreateInputRoundSignaturePair();

            await using ArenaRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc());
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(new[] { inputSigPair, inputSigPair }, round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.NonUniqueInputs, ex.ErrorCode);

            await arena.StopAsync(CancellationToken.None);
        }
Пример #13
0
        public async Task TooMuchWeightAsync()
        {
            WabiSabiConfig cfg   = new() { RegistrableWeightCredentials = 1 };
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            using Key key = new();

            await using ArenaRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.TooMuchWeight, ex.ErrorCode);

            await arena.StopAsync(CancellationToken.None);
        }
        public async Task NotEnoughFundsAsync()
        {
            WabiSabiConfig cfg   = new() { MinRegistrableAmount = Money.Coins(2) };
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            using Key key = new();

            await using PostRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.NotEnoughFunds, ex.ErrorCode);

            await arena.StopAsync(CancellationToken.None);
        }
Пример #15
0
        public async Task InputNotWhitelistedAsync()
        {
            MockArena      arena = new();
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

            round.Alices.Add(new Alice(BitcoinFactory.CreateOutPoint()));
            Round blameRound = new(round);

            arena.OnTryGetRound = _ => blameRound;

            await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(blameRound);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.InputNotWhitelisted, ex.ErrorCode);
        }
Пример #16
0
        public async Task InputSpentAsync()
        {
            MockArena      arena = new();
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

            arena.OnTryGetRound = _ => round;
            MockRpcClient rpc = new();

            rpc.OnGetTxOutAsync = (_, _, _) => null;

            await using PostRequestHandler handler = new(cfg, new Prison(), arena, rpc);
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.InputSpent, ex.ErrorCode);
        }
Пример #17
0
        public async Task InputBannedAsync()
        {
            MockArena arena  = new();
            Prison    prison = new();
            var       pair   = WabiSabiFactory.CreateInputRoundSignaturePair();

            prison.Punish(pair.Input, Punishment.Banned, Guid.NewGuid());
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

            arena.OnTryGetRound = _ => round;

            await using PostRequestHandler handler = new(cfg, prison, arena, new MockRpcClient());
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(pair, round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.InputBanned, ex.ErrorCode);
        }
Пример #18
0
        public async Task InputCantBeNotedAsync()
        {
            Prison prison = new();
            var    pair   = WabiSabiFactory.CreateInputRoundSignaturePair();

            prison.Punish(pair.Input, Punishment.Noted, Guid.NewGuid());
            WabiSabiConfig cfg   = new() { AllowNotedInputRegistration = false };
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            await using ArenaRequestHandler handler = new(cfg, prison, arena, WabiSabiFactory.CreateMockRpc());
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(pair, round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.InputBanned, ex.ErrorCode);

            await arena.StopAsync(CancellationToken.None);
        }
Пример #19
0
        public async Task InputUnconfirmedAsync()
        {
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            MockRpcClient rpc = new();

            rpc.OnGetTxOutAsync = (_, _, _) => new() { Confirmations = 0 };

            await using ArenaRequestHandler handler = new(cfg, new(), arena, rpc);
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.InputUnconfirmed, ex.ErrorCode);

            await arena.StopAsync(CancellationToken.None);
        }
        public async Task SuccessAsync()
        {
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            using Key key = new();

            await using ArenaRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));

            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);
            var minAliceDeadline = DateTimeOffset.UtcNow + cfg.ConnectionConfirmationTimeout * 0.9;
            var resp             = await handler.RegisterInputAsync(req);

            AssertSingleAliceSuccessfullyRegistered(round, minAliceDeadline, resp);

            await arena.StopAsync(CancellationToken.None);
        }
Пример #21
0
        public async Task InputNotWhitelistedAsync()
        {
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

            round.Alices.Add(WabiSabiFactory.CreateAlice());
            Round blameRound = WabiSabiFactory.CreateBlameRound(round, cfg);

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

            using Key key = new();

            await using PostRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(blameRound);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.InputNotWhitelisted, ex.ErrorCode);

            await arena.StopAsync(CancellationToken.None);
        }
Пример #22
0
        public async Task InputRegistrationTimedoutAsync()
        {
            WabiSabiConfig cfg   = new() { StandardInputRegistrationTimeout = TimeSpan.Zero };
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            using Key key = new();

            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);

            await using ArenaRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            arena.Rounds.Add(round.Id, round);
            await RegisterAndAssertWrongPhaseAsync(req, handler);

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

            await arena.StopAsync(CancellationToken.None);
        }
Пример #23
0
        public async Task WrongPhaseAsync()
        {
            MockArena      arena = new();
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

            arena.OnTryGetRound = _ => round;

            var req = WabiSabiFactory.CreateInputsRegistrationRequest(round);

            foreach (Phase phase in Enum.GetValues(typeof(Phase)))
            {
                if (phase != Phase.InputRegistration)
                {
                    round.Phase = phase;
                    await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
                    var ex = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

                    Assert.Equal(WabiSabiProtocolErrorCode.WrongPhase, ex.ErrorCode);
                }
            }
        }
Пример #24
0
        public async Task InputWhitelistedAsync()
        {
            MockArena      arena = new();
            var            pair  = WabiSabiFactory.CreateInputRoundSignaturePair();
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

            round.Alices.Add(new Alice(pair.Input));
            Round blameRound = new(round);

            arena.OnTryGetRound = _ => blameRound;

            await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(pair, blameRound);

            var ex = await Assert.ThrowsAnyAsync <Exception>(async() => await handler.RegisterInputAsync(req));

            if (ex is WabiSabiProtocolException wspex)
            {
                Assert.NotEqual(WabiSabiProtocolErrorCode.InputNotWhitelisted, wspex.ErrorCode);
            }
        }
Пример #25
0
        public async Task AliceAlreadyRegisteredIntraRoundAsync()
        {
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            using Key key = new();

            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);

            // Make sure an Alice have already been registered with the same input.
            var anotherAlice = WabiSabiFactory.CreateAlice(req.InputRoundSignaturePairs);

            round.Alices.Add(anotherAlice);
            round.SetPhase(Phase.ConnectionConfirmation);

            await using ArenaRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));
            await RegisterAndAssertWrongPhaseAsync(req, handler);

            await arena.StopAsync(CancellationToken.None);
        }
Пример #26
0
        public async Task InputWhitelistedAsync()
        {
            var            pair  = WabiSabiFactory.CreateInputRoundSignaturePair();
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

            round.Alices.Add(WabiSabiFactory.CreateAlice(pair));
            Round blameRound = WabiSabiFactory.CreateBlameRound(round, cfg);

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

            await using PostRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc());
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(pair, blameRound);

            var ex = await Assert.ThrowsAnyAsync <Exception>(async() => await handler.RegisterInputAsync(req));

            if (ex is WabiSabiProtocolException wspex)
            {
                Assert.NotEqual(WabiSabiProtocolErrorCode.InputNotWhitelisted, wspex.ErrorCode);
            }

            await arena.StopAsync(CancellationToken.None);
        }
Пример #27
0
        public async Task ScriptNotAllowedAsync()
        {
            MockArena      arena = new();
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

            arena.OnTryGetRound = _ => round;
            MockRpcClient rpc = new();

            using Key key = new();

            rpc.OnGetTxOutAsync = (_, _, _) => new GetTxOutResponse
            {
                Confirmations = 1,
                TxOut         = new TxOut(Money.Coins(1), key.PubKey.GetScriptAddress(Network.Main))
            };

            await using PostRequestHandler handler = new(cfg, new Prison(), arena, rpc);
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(round);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

            Assert.Equal(WabiSabiProtocolErrorCode.ScriptNotAllowed, ex.ErrorCode);
        }
Пример #28
0
        public async Task InputImmatureAsync()
        {
            MockArena      arena = new();
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

            arena.OnTryGetRound = _ => round;
            MockRpcClient rpc = new();

            var req = WabiSabiFactory.CreateInputsRegistrationRequest(round);

            for (int i = 1; i <= 100; i++)
            {
                rpc.OnGetTxOutAsync = (_, _, _) => new GetTxOutResponse {
                    Confirmations = i, IsCoinBase = true
                };

                await using PostRequestHandler handler = new(cfg, new Prison(), arena, rpc);
                var ex = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

                Assert.Equal(WabiSabiProtocolErrorCode.InputImmature, ex.ErrorCode);
            }
        }
Пример #29
0
        public async Task InputRegistrationFullAsync()
        {
            WabiSabiConfig cfg   = new() { MaxInputCountByRound = 3 };
            var            round = WabiSabiFactory.CreateRound(cfg);

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

            using Key key = new();

            var req = WabiSabiFactory.CreateInputsRegistrationRequest(key, round);

            await using ArenaRequestHandler handler = new(cfg, new(), arena, WabiSabiFactory.CreateMockRpc(key));

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

            round.Alices.Add(WabiSabiFactory.CreateAlice());
            round.Alices.Add(WabiSabiFactory.CreateAlice(WabiSabiFactory.CreateInputRoundSignaturePairs(2)));
            await RegisterAndAssertWrongPhaseAsync(req, handler);

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

            await arena.StopAsync(CancellationToken.None);
        }
        public async Task TimeoutSufficientPeersAsync()
        {
            WabiSabiConfig cfg = new()
            {
                MaxInputCountByRound           = 2,
                MinInputCountByRoundMultiplier = 1,
                TransactionSigningTimeout      = TimeSpan.Zero,
                OutputRegistrationTimeout      = TimeSpan.Zero
            };
            var mockRpc = new MockRpcClient();

            mockRpc.OnSendRawTransactionAsync = _ => throw new RPCException(RPCErrorCode.RPC_TRANSACTION_REJECTED, "", null);

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

            // Create the round.
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            var round = Assert.Single(arena.Rounds).Value;

            // Register Alices.
            using Key key1 = new();
            using Key key2 = new();
            var irreq1 = WabiSabiFactory.CreateInputsRegistrationRequest(key1, round);
            var irres1 = await arena.RegisterInputAsync(
                irreq1.RoundId,
                irreq1.InputRoundSignaturePairs.ToDictionary(x => new Coin(x.Input, new TxOut(Money.Coins(1), key1.PubKey.GetSegwitAddress(Network.Main))), x => x.RoundSignature),
                irreq1.ZeroAmountCredentialRequests,
                irreq1.ZeroWeightCredentialRequests);

            var irreq2 = WabiSabiFactory.CreateInputsRegistrationRequest(key2, round);
            var irres2 = await arena.RegisterInputAsync(
                irreq2.RoundId,
                irreq2.InputRoundSignaturePairs.ToDictionary(x => new Coin(x.Input, new TxOut(Money.Coins(1), key2.PubKey.GetSegwitAddress(Network.Main))), x => x.RoundSignature),
                irreq2.ZeroAmountCredentialRequests,
                irreq2.ZeroWeightCredentialRequests);

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

            Assert.Equal(Phase.ConnectionConfirmation, round.Phase);
            var alice1 = round.Alices.Single(x => x.Id == irres1.AliceId);
            var alice2 = round.Alices.Single(x => x.Id == irres2.AliceId);

            // Confirm connections.
            var ccresps = new List <(ConnectionConfirmationResponse resp, WabiSabiClient amountClient, WabiSabiClient weightClient, Guid aliceId)>();
            var ccreq1  = WabiSabiFactory.CreateConnectionConfirmationRequest(round, irres1);
            var ccresp1 = await arena.ConfirmConnectionAsync(ccreq1.request);

            ccresps.Add((ccresp1, ccreq1.amountClient, ccreq1.weightClient, irres2.AliceId));
            ccreq1.amountClient.HandleResponse(ccresp1.RealAmountCredentials !, ccreq1.amountValidation);
            ccreq1.weightClient.HandleResponse(ccresp1.RealWeightCredentials !, ccreq1.weightValidation);

            var ccreq2  = WabiSabiFactory.CreateConnectionConfirmationRequest(round, irres2);
            var ccresp2 = await arena.ConfirmConnectionAsync(ccreq2.request);

            ccresps.Add((ccresp2, ccreq2.amountClient, ccreq2.weightClient, irres1.AliceId));
            ccreq2.amountClient.HandleResponse(ccresp2.RealAmountCredentials !, ccreq2.amountValidation);
            ccreq2.weightClient.HandleResponse(ccresp2.RealWeightCredentials !, ccreq2.weightValidation);
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

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

            // Register outputs.
            foreach (var orreq in WabiSabiFactory.CreateOutputRegistrationRequests(round, ccresps))
            {
                var orresp = await arena.RegisterOutputAsync(orreq);
            }

            // Make sure not all alices signed.
            var alice3 = WabiSabiFactory.CreateAlice();

            alice3.ConfirmedConnection = true;
            round.Alices.Add(alice3);
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

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

            var signedCoinJoin = round.Coinjoin.Clone();
            var coin1          = alice1.Coins.First();
            var coin2          = alice2.Coins.First();
            var idx1           = signedCoinJoin.Inputs.IndexOf(signedCoinJoin.Inputs.Single(x => x.PrevOut == coin1.Outpoint));
            var idx2           = signedCoinJoin.Inputs.IndexOf(signedCoinJoin.Inputs.Single(x => x.PrevOut == coin2.Outpoint));

            signedCoinJoin.Sign(key1.GetBitcoinSecret(Network.Main), coin1);
            var txsigreq1 = new TransactionSignaturesRequest(round.Id, new[] { new InputWitnessPair((uint)idx1, signedCoinJoin.Inputs[idx1].WitScript) });

            signedCoinJoin.Sign(key2.GetBitcoinSecret(Network.Main), coin2);
            var txsigreq2 = new TransactionSignaturesRequest(round.Id, new[] { new InputWitnessPair((uint)idx2, signedCoinJoin.Inputs[idx2].WitScript) });

            await arena.SignTransactionAsync(txsigreq1);

            await arena.SignTransactionAsync(txsigreq2);

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

            Assert.DoesNotContain(round.Id, arena.Rounds.Keys);
            Assert.Single(arena.Rounds.Where(x => x.Value.IsBlameRound));
            var badOutpoint = alice3.Coins.Select(x => x.Outpoint).First();

            Assert.Contains(badOutpoint, arena.Prison.GetInmates().Select(x => x.Utxo));

            var blameRound = arena.Rounds.Single(x => x.Value.IsBlameRound).Value;

            Assert.True(blameRound.IsBlameRound);
            Assert.NotNull(blameRound.BlameOf);
            Assert.Equal(round.Id, blameRound.BlameOf?.Id);

            var whitelist = blameRound.BlameWhitelist;

            Assert.Contains(alice1.Coins.Select(x => x.Outpoint).First(), whitelist);
            Assert.Contains(alice2.Coins.Select(x => x.Outpoint).First(), whitelist);
            Assert.DoesNotContain(badOutpoint, whitelist);

            await arena.StopAsync(CancellationToken.None);
        }
    }