示例#1
0
        public void TotMessageTest()
        {
            Assert.Equal(TotPurpose.Ping, TotPing.Instance.Purpose);
            Assert.Equal(TotPurpose.Pong, TotPong.Instance(TotMessageId.Random).Purpose);

            Assert.Equal(TotPurpose.Success, TotResponse.Success(TotMessageId.Random).Purpose);
            Assert.Equal(TotPurpose.BadRequest, TotResponse.BadRequest(TotMessageId.Random).Purpose);
            Assert.Equal(TotPurpose.VersionMismatch, TotResponse.VersionMismatch(TotMessageId.Random).Purpose);
            Assert.Equal(TotPurpose.UnsuccessfulRequest, TotResponse.UnsuccessfulRequest(TotMessageId.Random).Purpose);

            var x = new TotRequest("status");

            Assert.Equal(97, x.GetLastCellFullnessPercentage());
            Assert.Equal(1, x.GetNumberOfCells());
            Assert.Equal(497, x.GetNumberOfDummyBytesInLastCell());

            var messages = TotMessageBase.SplitByMessages(ByteHelpers.Combine(
                                                              TotPing.Instance.ToBytes(),
                                                              TotPong.Instance(TotMessageId.Random).ToBytes(),
                                                              TotResponse.BadRequest(TotMessageId.Random).ToBytes(),
                                                              TotResponse.Success(TotMessageId.Random).ToBytes(),
                                                              TotResponse.UnsuccessfulRequest(TotMessageId.Random).ToBytes(),
                                                              TotResponse.VersionMismatch(TotMessageId.Random).ToBytes(),
                                                              new TotRequest("fooPurpose", new TotContent("foo content")).ToBytes()));

            Assert.Equal(7, messages.Count());
        }
 public override byte[] ToBytes() => ByteHelpers.Combine(
     new byte[]
 {
     Ver.ToByte(), Cmd.ToByte(), Rsv.ToByte(), Atyp.ToByte()
 },
     DstAddr.ToBytes(),
     DstPort.ToBytes());
 public override byte[] ToBytes() => ByteHelpers.Combine(
     new byte[]
 {
     Ver.ToByte(),
     NMethods.ToByte()
 },
     Methods.ToBytes());
示例#4
0
        /// <param name="dstAddr">domain or IPv4</param>
        public AddrField(string dstAddr)
        {
            dstAddr = Guard.NotNullOrEmptyOrWhitespace(nameof(dstAddr), dstAddr, true);

            var atyp = new AtypField();

            atyp.FromDstAddr(dstAddr);

            Atyp = atyp;

            byte[] bytes;
            if (atyp == AtypField.DomainName)
            {
                // https://www.ietf.org/rfc/rfc1928.txt
                // the address field contains a fully-qualified domain name.  The first
                // octet of the address field contains the number of octets of name that
                // follow, there is no terminating NUL octet.
                var domainBytes    = Encoding.ASCII.GetBytes(dstAddr);              // Tor only knows ASCII, UTF8 results in general SOCKS server failure
                var numberOfOctets = domainBytes.Length;
                if (numberOfOctets > 255)
                {
                    throw new FormatException($"{nameof(dstAddr)} can be maximum 255 octets. Actual: {numberOfOctets} octets. Value: {dstAddr}.");
                }

                bytes = ByteHelpers.Combine(new byte[] { (byte)numberOfOctets }, domainBytes);
            }
            else if (atyp == AtypField.IPv4)
            {
                // the address is a version-4 IP address, with a length of 4 octets
                var parts = dstAddr.Split(".", StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length != 4 || parts.Any(string.IsNullOrWhiteSpace))
                {
                    throw new FormatException($"{nameof(dstAddr)} must be have 4 parts. Actual: {parts.Length} parts. Value: {dstAddr}.");
                }

                bytes = new byte[4];
                for (int i = 0; i < 4; i++)
                {
                    if (int.TryParse(parts[i], out int partInt))
                    {
                        if (partInt < 0 || partInt > 255)
                        {
                            throw new FormatException($"Every part of {nameof(dstAddr)} must be between 0 and 255. The {i}. part is invalid: {partInt}. Value of {nameof(dstAddr)}: {dstAddr}");
                        }
                        bytes[i] = (byte)partInt;
                    }
                    else
                    {
                        throw new FormatException($"Could not parse the {i}. part of {nameof(dstAddr)} to int. Invalid part: {partInt}. Value of {nameof(dstAddr)}: {dstAddr}.");
                    }
                }
            }
            else
            {
                throw new NotSupportedException($"{nameof(atyp)} is not supported. Value: {atyp}.");
            }

            Bytes = bytes;
        }
示例#5
0
 public byte[] ToBytes(bool startsWithLength)
 {
     if (!startsWithLength)
     {
         return(Purpose);
     }
     return(ByteHelpers.Combine(new byte[] { BitConverter.GetBytes(Length)[0] }, Purpose));
 }
示例#6
0
        private static byte[] CreateHmac(byte[] salt, AesCryptoServiceProvider aes, byte[] encryptedMessage)
        {
            using (var hmacsha256 = new HMACSHA256(aes.Key))
            {
                var messagePlusSalt = ByteHelpers.Combine(encryptedMessage, salt);

                return(hmacsha256.ComputeHash(messagePlusSalt));
            }
        }
示例#7
0
        public byte[] ToBytes(bool startsWithLength)
        {
            if (!startsWithLength)
            {
                return(Content);
            }

            return(ByteHelpers.Combine(BitConverter.GetBytes(Length), Content));
        }
示例#8
0
        public Strobe128(string procotol)
        {
            Guard.NotNullOrEmpty(nameof(procotol), procotol);

            var initialState = ByteHelpers.Combine(
                new byte[] { 1, SpongeRate + 2, 1, 0, 1, 12 * 8 },                  // F([[1, r/8, 1, 0, 1, 12·8]]
                Encoding.UTF8.GetBytes("STROBEv1.0.2"));

            Buffer.BlockCopy(initialState, 0, State, 0, initialState.Length);
            KeccakF1600(State);
            AddAssociatedMetaData(Encoding.UTF8.GetBytes(procotol), false);
        }
示例#9
0
        public void CombineMergesToArraysTogether()
        {
            byte[] test  = { 1, 2 };
            byte[] test2 = { 3, 4 };

            byte[] combined = ByteHelpers.Combine(test, test2);

            Assert.AreEqual(4, combined.Length);
            Assert.AreEqual(1, combined[0]);
            Assert.AreEqual(2, combined[1]);
            Assert.AreEqual(3, combined[2]);
            Assert.AreEqual(4, combined[3]);
        }
示例#10
0
        public byte[] Encrypt(byte[] dataToEncrypt, string password, byte[] salt, int pbkdfRounds)
        {
            if (dataToEncrypt == null)
            {
                throw new ArgumentNullException("dataToEncrypt");
            }

            if (dataToEncrypt.Length == 0)
            {
                throw new InvalidOperationException("dataToEncrypt");
            }

            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentNullException("password");
            }

            try
            {
                using (var rfc2898 = new Rfc2898DeriveBytes(password, salt, pbkdfRounds))
                {
                    using (var aes = new AesCryptoServiceProvider())
                    {
                        aes.Mode    = CipherMode.CBC;
                        aes.Padding = PaddingMode.PKCS7;

                        aes.Key = rfc2898.GetBytes(32);
                        aes.IV  = rfc2898.GetBytes(16);

                        using (var memoryStream = new MemoryStream())
                        {
                            var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
                            cryptoStream.Write(dataToEncrypt, 0, dataToEncrypt.Length);
                            cryptoStream.FlushFinalBlock();

                            var encryptedMessage = memoryStream.ToArray();

                            byte[] hmac            = CreateHmac(salt, aes, encryptedMessage);
                            byte[] messagePlusHmac = ByteHelpers.Combine(hmac, encryptedMessage);

                            return(messagePlusHmac);
                        }
                    }
                }
            }
            catch
            {
                return(null);
            }
        }
示例#11
0
        /// <summary>
        /// Fiat Shamir heuristic.
        /// </summary>
        private static Scalar HashToScalar(IEnumerable <GroupElement> transcript)
        {
            var transcriptBytes = transcript.Select(x => x.ToBytes());
            // Make sure the length of the data is also committed to: len(data) || data
            // https://github.com/zkSNACKs/WalletWasabi/pull/4151#discussion_r470334048
            var concatenation = transcriptBytes
                                .SelectMany(x => ByteHelpers.Combine(BitConverter.GetBytes(x.Length), x))
                                .ToArray();

            using var sha256 = System.Security.Cryptography.SHA256.Create();
            var hash      = sha256.ComputeHash(concatenation);
            var challenge = new Scalar(hash);

            return(challenge);
        }
 public override byte[] ToBytes() => ByteHelpers.Combine(new byte[] { Ver.ToByte(), Rep.ToByte(), Rsv.ToByte(), Atyp.ToByte() }, BndAddr.ToBytes(), BndPort.ToBytes());
示例#13
0
        public void CombineThrowsArgumentNullExceptionIfSecondParameterIsNull()
        {
            var test = new byte[5];

            ByteHelpers.Combine(test, null);
        }
示例#14
0
 public void CombineThrowsArgumentNullExceptionIfFirstParameterIsNull()
 {
     ByteHelpers.Combine(null, null);
 }
示例#15
0
        public async Task <IActionResult> PostInputsAsync([FromBody, Required] InputsRequest request)
        {
            // Validate request.
            if (request.RoundId < 0 || !ModelState.IsValid)
            {
                return(BadRequest("Invalid request."));
            }

            if (request.Inputs.Count() > 7)
            {
                return(BadRequest("Maximum 7 inputs can be registered."));
            }

            using (await InputsLock.LockAsync())
            {
                CoordinatorRound round = Coordinator.TryGetRound(request.RoundId);

                if (round is null || round.Phase != RoundPhase.InputRegistration)
                {
                    return(NotFound("No such running round in InputRegistration. Try another round."));
                }

                // Do more checks.
                try
                {
                    uint256[] blindedOutputs        = request.BlindedOutputScripts.ToArray();
                    int       blindedOutputCount    = blindedOutputs.Length;
                    int       maxBlindedOutputCount = round.MixingLevels.Count();
                    if (blindedOutputCount > maxBlindedOutputCount)
                    {
                        return(BadRequest($"Too many blinded output was provided: {blindedOutputCount}, maximum: {maxBlindedOutputCount}."));
                    }

                    if (blindedOutputs.Distinct().Count() < blindedOutputs.Length)
                    {
                        return(BadRequest("Duplicate blinded output found."));
                    }

                    if (round.ContainsAnyBlindedOutputScript(blindedOutputs))
                    {
                        return(BadRequest("Blinded output has already been registered."));
                    }

                    if (request.ChangeOutputAddress.Network != Network)
                    {
                        // RegTest and TestNet address formats are sometimes the same.
                        if (Network == Network.Main)
                        {
                            return(BadRequest($"Invalid ChangeOutputAddress Network."));
                        }
                    }

                    var uniqueInputs = new HashSet <OutPoint>();
                    foreach (InputProofModel inputProof in request.Inputs)
                    {
                        var outpoint = inputProof.Input.ToOutPoint();
                        if (uniqueInputs.Contains(outpoint))
                        {
                            return(BadRequest("Cannot register an input twice."));
                        }
                        uniqueInputs.Add(outpoint);
                    }

                    var alicesToRemove    = new HashSet <Guid>();
                    var getTxOutResponses = new List <(InputProofModel inputModel, Task <GetTxOutResponse> getTxOutTask)>();

                    var batch = RpcClient.PrepareBatch();

                    foreach (InputProofModel inputProof in request.Inputs)
                    {
                        if (round.ContainsInput(inputProof.Input.ToOutPoint(), out List <Alice> tr))
                        {
                            alicesToRemove.UnionWith(tr.Select(x => x.UniqueId));                             // Input is already registered by this alice, remove it later if all the checks are completed fine.
                        }
                        if (Coordinator.AnyRunningRoundContainsInput(inputProof.Input.ToOutPoint(), out List <Alice> tnr))
                        {
                            if (tr.Union(tnr).Count() > tr.Count)
                            {
                                return(BadRequest("Input is already registered in another round."));
                            }
                        }

                        OutPoint outpoint   = inputProof.Input.ToOutPoint();
                        var      bannedElem = await Coordinator.UtxoReferee.TryGetBannedAsync(outpoint, notedToo : false);

                        if (bannedElem != null)
                        {
                            return(BadRequest($"Input is banned from participation for {(int)bannedElem.BannedRemaining.TotalMinutes} minutes: {inputProof.Input.Index}:{inputProof.Input.TransactionId}."));
                        }

                        var txOutResponseTask = batch.GetTxOutAsync(inputProof.Input.TransactionId, (int)inputProof.Input.Index, includeMempool: true);
                        getTxOutResponses.Add((inputProof, txOutResponseTask));
                    }

                    // Perform all RPC request at once
                    var waiting = Task.WhenAll(getTxOutResponses.Select(x => x.getTxOutTask));
                    await batch.SendBatchAsync();

                    await waiting;

                    byte[]  blindedOutputScriptHashesByte = ByteHelpers.Combine(blindedOutputs.Select(x => x.ToBytes()));
                    uint256 blindedOutputScriptsHash      = new uint256(Hashes.SHA256(blindedOutputScriptHashesByte));

                    var inputs = new HashSet <Coin>();

                    foreach (var responses in getTxOutResponses)
                    {
                        var(inputProof, getTxOutResponseTask) = responses;
                        var getTxOutResponse = await getTxOutResponseTask;

                        // Check if inputs are unspent.
                        if (getTxOutResponse is null)
                        {
                            return(BadRequest($"Provided input is not unspent: {inputProof.Input.Index}:{inputProof.Input.TransactionId}."));
                        }

                        // Check if unconfirmed.
                        if (getTxOutResponse.Confirmations <= 0)
                        {
                            // If it spends a CJ then it may be acceptable to register.
                            if (!await Coordinator.ContainsUnconfirmedCoinJoinAsync(inputProof.Input.TransactionId))
                            {
                                return(BadRequest("Provided input is neither confirmed, nor is from an unconfirmed coinjoin."));
                            }

                            // Check if mempool would accept a fake transaction created with the registered inputs.
                            // This will catch ascendant/descendant count and size limits for example.
                            var result = await RpcClient.TestMempoolAcceptAsync(new[] { new Coin(inputProof.Input.ToOutPoint(), getTxOutResponse.TxOut) });

                            if (!result.accept)
                            {
                                return(BadRequest($"Provided input is from an unconfirmed coinjoin, but a limit is reached: {result.rejectReason}"));
                            }
                        }

                        // Check if immature.
                        if (getTxOutResponse.Confirmations <= 100)
                        {
                            if (getTxOutResponse.IsCoinBase)
                            {
                                return(BadRequest("Provided input is immature."));
                            }
                        }

                        // Check if inputs are native segwit.
                        if (getTxOutResponse.ScriptPubKeyType != "witness_v0_keyhash")
                        {
                            return(BadRequest("Provided input must be witness_v0_keyhash."));
                        }

                        TxOut txOut = getTxOutResponse.TxOut;

                        var address = (BitcoinWitPubKeyAddress)txOut.ScriptPubKey.GetDestinationAddress(Network);
                        // Check if proofs are valid.
                        if (!address.VerifyMessage(blindedOutputScriptsHash, inputProof.Proof))
                        {
                            return(BadRequest("Provided proof is invalid."));
                        }

                        inputs.Add(new Coin(inputProof.Input.ToOutPoint(), txOut));
                    }

                    var acceptedBlindedOutputScripts = new List <uint256>();

                    // Calculate expected networkfee to pay after base denomination.
                    int   inputCount = inputs.Count;
                    Money networkFeeToPayAfterBaseDenomination = (inputCount * round.FeePerInputs) + (2 * round.FeePerOutputs);

                    // Check if inputs have enough coins.
                    Money inputSum     = inputs.Sum(x => x.Amount);
                    Money changeAmount = (inputSum - (round.MixingLevels.GetBaseDenomination() + networkFeeToPayAfterBaseDenomination));
                    if (changeAmount < Money.Zero)
                    {
                        return(BadRequest($"Not enough inputs are provided. Fee to pay: {networkFeeToPayAfterBaseDenomination.ToString(false, true)} BTC. Round denomination: {round.MixingLevels.GetBaseDenomination().ToString(false, true)} BTC. Only provided: {inputSum.ToString(false, true)} BTC."));
                    }
                    acceptedBlindedOutputScripts.Add(blindedOutputs.First());

                    Money networkFeeToPay = networkFeeToPayAfterBaseDenomination;
                    // Make sure we sign the proper number of additional blinded outputs.
                    var moneySoFar = Money.Zero;
                    for (int i = 1; i < blindedOutputCount; i++)
                    {
                        if (!round.MixingLevels.TryGetDenomination(i, out Money denomination))
                        {
                            break;
                        }

                        Money coordinatorFee = denomination.Percentage(round.CoordinatorFeePercent * round.AnonymitySet);                         // It should be the number of bobs, but we must make sure they'd have money to pay all.
                        changeAmount    -= (denomination + round.FeePerOutputs + coordinatorFee);
                        networkFeeToPay += round.FeePerOutputs;

                        if (changeAmount < Money.Zero)
                        {
                            break;
                        }

                        acceptedBlindedOutputScripts.Add(blindedOutputs[i]);
                    }

                    // Make sure Alice checks work.
                    var alice = new Alice(inputs, networkFeeToPayAfterBaseDenomination, request.ChangeOutputAddress, acceptedBlindedOutputScripts);

                    foreach (Guid aliceToRemove in alicesToRemove)
                    {
                        round.RemoveAlicesBy(aliceToRemove);
                    }
                    round.AddAlice(alice);

                    // All checks are good. Sign.
                    var blindSignatures = new List <uint256>();
                    for (int i = 0; i < acceptedBlindedOutputScripts.Count; i++)
                    {
                        var     blindedOutput  = acceptedBlindedOutputScripts[i];
                        var     signer         = round.MixingLevels.GetLevel(i).Signer;
                        uint256 blindSignature = signer.Sign(blindedOutput);
                        blindSignatures.Add(blindSignature);
                    }
                    alice.BlindedOutputSignatures = blindSignatures.ToArray();

                    // Check if phase changed since.
                    if (round.Status != CoordinatorRoundStatus.Running || round.Phase != RoundPhase.InputRegistration)
                    {
                        return(StatusCode(StatusCodes.Status503ServiceUnavailable, "The state of the round changed while handling the request. Try again."));
                    }

                    // Progress round if needed.
                    if (round.CountAlices() >= round.AnonymitySet)
                    {
                        await round.RemoveAlicesIfAnInputRefusedByMempoolAsync();

                        if (round.CountAlices() >= round.AnonymitySet)
                        {
                            await round.ExecuteNextPhaseAsync(RoundPhase.ConnectionConfirmation);
                        }
                    }

                    var resp = new InputsResponse
                    {
                        UniqueId = alice.UniqueId,
                        RoundId  = round.RoundId
                    };
                    return(Ok(resp));
                }
                catch (Exception ex)
                {
                    Logger.LogDebug(ex);
                    return(BadRequest(ex.Message));
                }
            }
        }
示例#16
0
        private async Task TryRegisterCoinsAsync(CcjClientRound inputRegistrableRound)
        {
            try
            {
                // Select the most suitable coins to regiter.
                List <TxoRef> registrableCoins = State.GetRegistrableCoins(
                    inputRegistrableRound.State.MaximumInputCountPerPeer,
                    inputRegistrableRound.State.Denomination,
                    inputRegistrableRound.State.FeePerInputs,
                    inputRegistrableRound.State.FeePerOutputs).ToList();

                // If there are no suitable coins to register return.
                if (!registrableCoins.Any())
                {
                    return;
                }

                (HdPubKey change, IEnumerable <HdPubKey> actives)outputAddresses = GetOutputsToRegister(inputRegistrableRound.State.Denomination, inputRegistrableRound.State.SchnorrPubKeys.Count(), registrableCoins);

                SchnorrPubKey[]  schnorrPubKeys = inputRegistrableRound.State.SchnorrPubKeys.ToArray();
                List <Requester> requesters     = new List <Requester>();
                var blindedOutputScriptHashes   = new List <uint256>();

                var registeredAddresses = new List <BitcoinAddress>();
                for (int i = 0; i < schnorrPubKeys.Length; i++)
                {
                    if (outputAddresses.actives.Count() <= i)
                    {
                        break;
                    }

                    BitcoinAddress address = outputAddresses.actives.Select(x => x.GetP2wpkhAddress(Network)).ElementAt(i);

                    SchnorrPubKey schnorrPubKey           = schnorrPubKeys[i];
                    var           outputScriptHash        = new uint256(Hashes.SHA256(address.ScriptPubKey.ToBytes()));
                    var           requester               = new Requester();
                    uint256       blindedOutputScriptHash = requester.BlindMessage(outputScriptHash, schnorrPubKey);
                    requesters.Add(requester);
                    blindedOutputScriptHashes.Add(blindedOutputScriptHash);
                    registeredAddresses.Add(address);
                }

                byte[]  blindedOutputScriptHashesByte = ByteHelpers.Combine(blindedOutputScriptHashes.Select(x => x.ToBytes()));
                uint256 blindedOutputScriptsHash      = new uint256(Hashes.SHA256(blindedOutputScriptHashesByte));

                var inputProofs = new List <InputProofModel>();
                foreach (TxoRef coinReference in registrableCoins)
                {
                    SmartCoin coin = State.GetSingleOrDefaultFromWaitingList(coinReference);
                    if (coin is null)
                    {
                        throw new NotSupportedException("This is impossible.");
                    }

                    coin.Secret = coin.Secret ?? KeyManager.GetSecrets(SaltSoup(), coin.ScriptPubKey).Single();
                    var inputProof = new InputProofModel {
                        Input = coin.GetTxoRef(),
                        Proof = coin.Secret.PrivateKey.SignCompact(blindedOutputScriptsHash)
                    };
                    inputProofs.Add(inputProof);
                }

                AliceClient aliceClient = null;
                try
                {
                    aliceClient = await AliceClient.CreateNewAsync(inputRegistrableRound.RoundId, registeredAddresses, schnorrPubKeys, requesters, Network, outputAddresses.change.GetP2wpkhAddress(Network), blindedOutputScriptHashes, inputProofs, CcjHostUriAction, TorSocks5EndPoint);
                }
                catch (HttpRequestException ex) when(ex.Message.Contains("Input is banned", StringComparison.InvariantCultureIgnoreCase))
                {
                    string[] parts             = ex.Message.Split(new[] { "Input is banned from participation for ", " minutes: " }, StringSplitOptions.RemoveEmptyEntries);
                    string   minutesString     = parts[1];
                    int      minuteInt         = int.Parse(minutesString);
                    string   bannedInputString = parts[2].TrimEnd('.');

                    string[]  bannedInputStringParts = bannedInputString.Split(':', StringSplitOptions.RemoveEmptyEntries);
                    TxoRef    coinReference          = new TxoRef(new uint256(bannedInputStringParts[1]), uint.Parse(bannedInputStringParts[0]));
                    SmartCoin coin = State.GetSingleOrDefaultFromWaitingList(coinReference);

                    if (coin is null)
                    {
                        throw new NotSupportedException("This is impossible.");
                    }

                    coin.BannedUntilUtc = DateTimeOffset.UtcNow + TimeSpan.FromMinutes(minuteInt);

                    Logger.LogWarning <CcjClient>(ex.Message.Split('\n')[1]);

                    await DequeueCoinsFromMixNoLockAsync(coinReference, "Failed to register the coin with the coordinator.");

                    aliceClient?.Dispose();
                    return;
                }
                catch (HttpRequestException ex) when(ex.Message.Contains("Provided input is not unspent", StringComparison.InvariantCultureIgnoreCase))
                {
                    string[] parts            = ex.Message.Split(new[] { "Provided input is not unspent: " }, StringSplitOptions.RemoveEmptyEntries);
                    string   spentInputString = parts[1].TrimEnd('.');

                    string[]  bannedInputStringParts = spentInputString.Split(':', StringSplitOptions.RemoveEmptyEntries);
                    TxoRef    coinReference          = new TxoRef(new uint256(bannedInputStringParts[1]), uint.Parse(bannedInputStringParts[0]));
                    SmartCoin coin = State.GetSingleOrDefaultFromWaitingList(coinReference);

                    if (coin is null)
                    {
                        throw new NotSupportedException("This is impossible.");
                    }

                    coin.SpentAccordingToBackend = true;

                    Logger.LogWarning <CcjClient>(ex.Message.Split('\n')[1]);

                    await DequeueCoinsFromMixNoLockAsync(coinReference, "Failed to register the coin with the coordinator. The coin is already spent.");

                    aliceClient?.Dispose();
                    return;
                }
                catch (HttpRequestException ex) when(ex.Message.Contains("No such running round in InputRegistration.", StringComparison.InvariantCultureIgnoreCase))
                {
                    Logger.LogInfo <CcjClient>("Client tried to register a round that is not in InputRegistration anymore. Trying again later.");
                    aliceClient?.Dispose();
                    return;
                }
                catch (HttpRequestException ex) when(ex.Message.Contains("too-long-mempool-chain", StringComparison.InvariantCultureIgnoreCase))
                {
                    Logger.LogInfo <CcjClient>("Coordinator failed because too much unconfirmed parent transactions. Trying again later.");
                    aliceClient?.Dispose();
                    return;
                }

                var coinsRegistered = new List <SmartCoin>();
                foreach (TxoRef coinReference in registrableCoins)
                {
                    var coin = State.GetSingleOrDefaultFromWaitingList(coinReference);
                    if (coin is null)
                    {
                        throw new NotSupportedException("This is impossible.");
                    }

                    coinsRegistered.Add(coin);
                    State.RemoveCoinFromWaitingList(coin);
                }

                var registration = new ClientRoundRegistration(aliceClient, coinsRegistered, outputAddresses.change.GetP2wpkhAddress(Network));

                CcjClientRound roundRegistered = State.GetSingleOrDefaultRound(aliceClient.RoundId);
                if (roundRegistered is null)
                {
                    // If our SatoshiClient does not yet know about the round, because of delay, then delay the round registration.
                    DelayedRoundRegistration?.Dispose();
                    DelayedRoundRegistration = registration;
                }

                roundRegistered.Registration = registration;
            }
            catch (Exception ex)
            {
                Logger.LogError <CcjClient>(ex);
            }
        }
 public override byte[] ToBytes() => ByteHelpers.Combine(new byte[] { Ver.ToByte(), ULen.ToByte() }, UName.ToBytes(), new byte[] { PLen.ToByte() }, Passwd.ToBytes());
示例#18
0
 public override byte[] ToBytes() => ByteHelpers.Combine(new byte[] { Version.ToByte(), MessageType.ToByte() }, MessageId.ToBytes(), Purpose.ToBytes(startsWithLength: true), Content.ToBytes(startsWithLength: true));