Exemple #1
0
        public async Task <Coin> OutpointToCoinAsync(InputRegistrationRequest request, CancellationToken cancellationToken)
        {
            OutPoint input = request.Input;

            if (Prison.TryGet(input, out var inmate) && (!Config.AllowNotedInputRegistration || inmate.Punishment != Punishment.Noted))
            {
                throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputBanned);
            }

            var txOutResponse = await Rpc.GetTxOutAsync(input.Hash, (int)input.N, includeMempool : true, cancellationToken).ConfigureAwait(false);

            if (txOutResponse is null)
            {
                throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputSpent);
            }
            if (txOutResponse.Confirmations == 0)
            {
                throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputUnconfirmed);
            }
            if (txOutResponse.IsCoinBase && txOutResponse.Confirmations <= 100)
            {
                throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputImmature);
            }

            return(new Coin(input, txOutResponse.TxOut));
        }
        public void EmptyPrison()
        {
            var p = new Prison();

            Assert.Empty(p.GetInmates());
            Assert.Equal(0, p.CountInmates().noted);
            Assert.Equal(0, p.CountInmates().banned);
            Assert.False(p.TryGet(BitcoinFactory.CreateOutPoint(), out _));
        }
        public void PrisonOperations()
        {
            var p = new Prison();

            var id1 = BitcoinFactory.CreateUint256();

            var utxo = BitcoinFactory.CreateOutPoint();

            p.Punish(utxo, Punishment.Noted, id1);
            Assert.Single(p.GetInmates());
            Assert.Equal(1, p.CountInmates().noted);
            Assert.Equal(0, p.CountInmates().banned);
            Assert.True(p.TryGet(utxo, out _));

            // Updates to banned.
            p.Punish(utxo, Punishment.Banned, id1);
            Assert.Single(p.GetInmates());
            Assert.Equal(0, p.CountInmates().noted);
            Assert.Equal(1, p.CountInmates().banned);
            Assert.True(p.TryGet(utxo, out _));

            // Removes.
            Assert.True(p.TryRelease(utxo, out _));
            Assert.Empty(p.GetInmates());

            // Noting twice flips to banned.
            p.Punish(utxo, Punishment.Noted, id1);
            p.Punish(utxo, Punishment.Noted, id1);
            Assert.Single(p.GetInmates());
            Assert.Equal(0, p.CountInmates().noted);
            Assert.Equal(1, p.CountInmates().banned);
            Assert.True(p.TryGet(utxo, out _));
            Assert.True(p.TryRelease(utxo, out _));

            // Updates round.
            var id2 = BitcoinFactory.CreateUint256();

            p.Punish(utxo, Punishment.Banned, id1);
            p.Punish(utxo, Punishment.Banned, id2);
            Assert.Single(p.GetInmates());
            Assert.True(p.TryGet(utxo, out var inmate));
            Assert.Equal(id2, inmate !.LastDisruptedRoundId);
            Assert.True(p.TryRelease(utxo, out _));
        }
        public static async Task <IDictionary <Coin, byte[]> > PreProcessAsync(
            InputsRegistrationRequest request,
            Prison prison,
            IRPCClient rpc,
            WabiSabiConfig config)
        {
            var inputRoundSignaturePairs = request.InputRoundSignaturePairs;
            var inputs = inputRoundSignaturePairs.Select(x => x.Input);

            int inputCount = inputs.Count();

            if (inputCount != inputs.Distinct().Count())
            {
                throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.NonUniqueInputs);
            }
            if (inputs.Any(x => prison.TryGet(x, out var inmate) && (!config.AllowNotedInputRegistration || inmate.Punishment != Punishment.Noted)))
            {
                throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputBanned);
            }

            Dictionary <Coin, byte[]> coinRoundSignaturePairs = new();

            foreach (var inputRoundSignaturePair in inputRoundSignaturePairs)
            {
                OutPoint input         = inputRoundSignaturePair.Input;
                var      txOutResponse = await rpc.GetTxOutAsync(input.Hash, (int)input.N, includeMempool : true).ConfigureAwait(false);

                if (txOutResponse is null)
                {
                    throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputSpent);
                }
                if (txOutResponse.Confirmations == 0)
                {
                    throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputUnconfirmed);
                }
                if (txOutResponse.IsCoinBase && txOutResponse.Confirmations <= 100)
                {
                    throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputImmature);
                }
                if (!txOutResponse.TxOut.ScriptPubKey.IsScriptType(ScriptType.P2WPKH))
                {
                    throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.ScriptNotAllowed);
                }

                coinRoundSignaturePairs.Add(new Coin(input, txOutResponse.TxOut), inputRoundSignaturePair.RoundSignature);
            }

            return(coinRoundSignaturePairs);
        }
Exemple #5
0
    public async Task <Coin> OutpointToCoinAsync(InputRegistrationRequest request, CancellationToken cancellationToken)
    {
        OutPoint input = request.Input;

        if (Prison.TryGet(input, out var inmate))
        {
            DateTimeOffset bannedUntil;
            if (inmate.Punishment == Punishment.LongBanned)
            {
                bannedUntil = inmate.Started + Config.ReleaseUtxoFromPrisonAfterLongBan;
                throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputLongBanned, exceptionData: new InputBannedExceptionData(bannedUntil));
            }

            if (!Config.AllowNotedInputRegistration || inmate.Punishment != Punishment.Noted)
            {
                bannedUntil = inmate.Started + Config.ReleaseUtxoFromPrisonAfter;
                throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputBanned, exceptionData: new InputBannedExceptionData(bannedUntil));
            }
        }

        var txOutResponse = await Rpc.GetTxOutAsync(input.Hash, (int)input.N, includeMempool : true, cancellationToken).ConfigureAwait(false);

        if (txOutResponse is null)
        {
            throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputSpent);
        }
        if (txOutResponse.Confirmations == 0)
        {
            throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputUnconfirmed);
        }
        if (txOutResponse.IsCoinBase && txOutResponse.Confirmations <= 100)
        {
            throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InputImmature);
        }

        return(new Coin(input, txOutResponse.TxOut));
    }