public async Task CreatesRoundIfInBlameInputRegistrationAsync()
        {
            WabiSabiConfig cfg     = new();
            var            mockRpc = new MockRpcClient();

            mockRpc.OnEstimateSmartFeeAsync = async(target, _) =>
                                              await Task.FromResult(new EstimateSmartFeeResponse
            {
                Blocks  = target,
                FeeRate = new FeeRate(10m)
            });

            using Arena arena = new Arena(TimeSpan.FromSeconds(1), Network.Main, cfg, mockRpc, new Prison());
            Assert.Empty(arena.Rounds);
            await arena.StartAsync(CancellationToken.None).ConfigureAwait(false);

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

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

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

            Assert.Equal(Phase.InputRegistration, blameRound.Phase);
            arena.Rounds.Add(blameRound.Id, blameRound);
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21)).ConfigureAwait(false);

            Assert.Equal(3, arena.Rounds.Count);
            Assert.Equal(2, arena.Rounds.Where(x => x.Value.Phase == Phase.InputRegistration).Count());

            await arena.StopAsync(CancellationToken.None);
        }
    public async Task BlameRoundTimedoutWithSufficientInputsAsync()
    {
        WabiSabiConfig cfg = new()
        {
            BlameInputRegistrationTimeout    = TimeSpan.Zero,
            StandardInputRegistrationTimeout = TimeSpan.FromHours(1),             // Test that this is disregarded.
            MaxInputCountByRound             = 4,
            MinInputCountByRoundMultiplier   = 0.5
        };
        var round  = WabiSabiFactory.CreateRound(cfg);
        var alice1 = WabiSabiFactory.CreateAlice(round);
        var alice2 = WabiSabiFactory.CreateAlice(round);
        var alice3 = WabiSabiFactory.CreateAlice(round);

        round.Alices.Add(alice1);
        round.Alices.Add(alice2);
        round.Alices.Add(alice3);
        var blameRound = WabiSabiFactory.CreateBlameRound(round, cfg);

        blameRound.Alices.Add(alice1);
        blameRound.Alices.Add(alice2);

        using Arena arena = await ArenaBuilder.From(cfg).CreateAndStartAsync(blameRound);

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

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

        await arena.StopAsync(CancellationToken.None);
    }
Beispiel #3
0
        public async Task InputWhitelistedButBannedAsync()
        {
            using Key key = new();
            var alice      = WabiSabiFactory.CreateAlice(key);
            var bannedCoin = alice.Coin.Outpoint;

            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

            round.Alices.Add(alice);
            Round blameRound = WabiSabiFactory.CreateBlameRound(round, cfg);
            var   mockRpc    = WabiSabiFactory.CreatePreconfiguredRpcClient(alice.Coin);

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

            arena.Prison.Punish(bannedCoin, Punishment.Banned, uint256.Zero);
            await using ArenaRequestHandler handler = new(cfg, arena.Prison, arena, mockRpc.Object);

            var req = WabiSabiFactory.CreateInputRegistrationRequest(key: key, round: blameRound, prevout: bannedCoin);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req, CancellationToken.None));

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

            await arena.StopAsync(CancellationToken.None);
        }
    public async Task BlameRoundTimedoutWithoutSufficientInputsAsync()
    {
        // This test also tests that the min input count multiplier is applied
        // against the max input count by round number and not against the
        // number of inputs awaited by the blame round itself.
        WabiSabiConfig cfg = new()
        {
            BlameInputRegistrationTimeout    = TimeSpan.Zero,
            StandardInputRegistrationTimeout = TimeSpan.FromHours(1),             // Test that this is disregarded.
            MaxInputCountByRound             = 4,
            MinInputCountByRoundMultiplier   = 0.5
        };
        var round  = WabiSabiFactory.CreateRound(cfg);
        var alice1 = WabiSabiFactory.CreateAlice(round);
        var alice2 = WabiSabiFactory.CreateAlice(round);

        round.Alices.Add(alice1);
        round.Alices.Add(alice2);
        var blameRound = WabiSabiFactory.CreateBlameRound(round, cfg);

        blameRound.Alices.Add(alice1);

        using Arena arena = await ArenaBuilder.From(cfg).CreateAndStartAsync(blameRound);

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

        Assert.Equal(Phase.Ended, blameRound.Phase);
        Assert.DoesNotContain(blameRound, arena.GetActiveRounds());

        await arena.StopAsync(CancellationToken.None);
    }
Beispiel #5
0
        public async Task InputNotWhitelistedAsync()
        {
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);

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

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

            using Key key = new();
            var mockRpc = WabiSabiFactory.CreatePreconfiguredRpcClient();

            var req = WabiSabiFactory.CreateInputRegistrationRequest(round: blameRound);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await arena.RegisterInputAsync(req, CancellationToken.None));

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

            await arena.StopAsync(CancellationToken.None);
        }
Beispiel #6
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);
        }
Beispiel #7
0
        public async Task InputWhitelistedAsync()
        {
            WabiSabiConfig cfg   = new();
            var            round = WabiSabiFactory.CreateRound(cfg);
            var            alice = WabiSabiFactory.CreateAlice(round);

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

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

            var req = WabiSabiFactory.CreateInputRegistrationRequest(prevout: alice.Coin.Outpoint, round: blameRound);

            var ex = await Assert.ThrowsAnyAsync <Exception>(async() => await arena.RegisterInputAsync(req, CancellationToken.None));

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

            await arena.StopAsync(CancellationToken.None);
        }
Beispiel #8
0
        public async Task InputWhitelistedButBannedAsync()
        {
            Prison prison = new();
            var    pair   = WabiSabiFactory.CreateInputRoundSignaturePair();

            prison.Punish(pair.Input, Punishment.Banned, Guid.NewGuid());
            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, prison, arena, WabiSabiFactory.CreateMockRpc());
            var req = WabiSabiFactory.CreateInputsRegistrationRequest(pair, blameRound);
            var ex  = await Assert.ThrowsAsync <WabiSabiProtocolException>(async() => await handler.RegisterInputAsync(req));

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

            await arena.StopAsync(CancellationToken.None);
        }
Beispiel #9
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);
        }
    public async Task BlameRoundFullAsync()
    {
        WabiSabiConfig cfg = new()
        {
            MaxInputCountByRound           = 4,
            MinInputCountByRoundMultiplier = 0.5
        };
        var round  = WabiSabiFactory.CreateRound(cfg);
        var alice1 = WabiSabiFactory.CreateAlice(round);
        var alice2 = WabiSabiFactory.CreateAlice(round);
        var alice3 = WabiSabiFactory.CreateAlice(round);

        round.Alices.Add(alice1);
        round.Alices.Add(alice2);
        round.Alices.Add(alice3);
        var blameRound = WabiSabiFactory.CreateBlameRound(round, cfg);

        using Arena arena = await ArenaBuilder.From(cfg).CreateAndStartAsync(blameRound);

        blameRound.Alices.Add(alice1);
        await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

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

        blameRound.Alices.Add(alice2);
        await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

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

        blameRound.Alices.Add(alice3);
        await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

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

        await arena.StopAsync(CancellationToken.None);
    }