/// <inheritdoc />
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var epk = (ExtPubKey)value;
            var hex = ByteHelpers.ToHex(epk.ToBytes());

            writer.WriteValue(hex);
        }
Пример #2
0
        public static string GenerateSha256Hash(string input)
        {
            using var sha256 = SHA256.Create();
            var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(input));

            return(ByteHelpers.ToHex(hash));
        }
Пример #3
0
        /// <summary>Connects to Tor control using a TCP client or throws <see cref="TorControlException"/>.</summary>
        /// <exception cref="TorControlException">When authentication fails for some reason.</exception>
        /// <seealso href="https://gitweb.torproject.org/torspec.git/tree/control-spec.txt">This method follows instructions in 3.23. TAKEOWNERSHIP.</seealso>
        private async Task <TorControlClient> InitTorControlAsync(CancellationToken token = default)
        {
            // Get cookie.
            string cookieString = ByteHelpers.ToHex(File.ReadAllBytes(Settings.CookieAuthFilePath));

            // Authenticate.
            TorControlClientFactory factory = new();
            TorControlClient        client  = await factory.ConnectAndAuthenticateAsync(Settings.ControlEndpoint, cookieString, token).ConfigureAwait(false);

            if (Settings.TerminateOnExit)
            {
                // This is necessary for the scenario when Tor was started by a previous WW instance with TerminateTorOnExit=false configuration option.
                TorControlReply takeReply = await client.TakeOwnershipAsync(token).ConfigureAwait(false);

                if (!takeReply)
                {
                    throw new TorControlException($"Failed to take ownership of the Tor instance. Reply: '{takeReply}'.");
                }

                TorControlReply resetReply = await client.ResetOwningControllerProcessConfAsync(token).ConfigureAwait(false);

                if (!resetReply)
                {
                    throw new TorControlException($"Failed to reset __OwningControllerProcess. Reply: '{resetReply}'.");
                }
            }

            return(client);
        }
Пример #4
0
    public void ConverterTest()
    {
        // Get a compressed private key.
        string        base58        = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw";
        BitcoinSecret bitcoinSecret = Network.Main.CreateBitcoinSecret(base58);
        Key           privateKey    = bitcoinSecret.PrivateKey;

        Assert.True(privateKey.IsCompressed);

        uint256          hashMsg           = Hashes.DoubleSHA256(Encoding.ASCII.GetBytes("compact hashing test"));
        CompactSignature expectedSignature = privateKey.SignCompact(hashMsg);

        Assert.NotNull(expectedSignature);

        byte[] sigBytes = CompactSignatureJsonConverter.ToBytes(expectedSignature);
        string hex      = ByteHelpers.ToHex(sigBytes);

        Assert.Equal("1F71932FFF735FA6A57787191A296717F71270B2B7E1D90008B7147117F250DBDE012359EED51D28682B1AAB686A8FD8A411A8D07F1EB4D7CDAC5B7EBE73F260A0", hex);

        CompactSignatureJsonConverter converter = new();
        string json = JsonConvert.SerializeObject(expectedSignature, converter);

        Assert.Equal("\"H3GTL/9zX6ald4cZGilnF/cScLK34dkACLcUcRfyUNveASNZ7tUdKGgrGqtoao/YpBGo0H8etNfNrFt+vnPyYKA=\"", json);

        CompactSignature?actual = JsonConvert.DeserializeObject <CompactSignature>(json, converter);

        Assert.NotNull(actual);

        Assert.Equal(actual !.RecoveryId, expectedSignature.RecoveryId);
        Assert.Equal(actual.Signature, expectedSignature.Signature);
    }
Пример #5
0
        public void FromText(string text, string expectedHex)
        {
            var ge  = Generators.FromText(text);
            var hex = ByteHelpers.ToHex(ge.ToBytes());

            Assert.Equal(expectedHex, hex);
        }
		public string ToHex(bool xhhSyntax = false)
		{
			if (xhhSyntax)
			{
				return $"X'{ByteHelpers.ToHex(ToByte())}'";
			}
			return ByteHelpers.ToHex(ToByte());
		}
Пример #7
0
 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
 {
     if (value is GroupElement ge)
     {
         writer.WriteValue(ByteHelpers.ToHex(ge.ToBytes()));
         return;
     }
     throw new ArgumentException($"No valid {nameof(GroupElement)}.", nameof(value));
 }
Пример #8
0
 /// <inheritdoc />
 public override void WriteJson(JsonWriter writer, Scalar value, JsonSerializer serializer)
 {
     if (value is Scalar scalar)
     {
         writer.WriteValue(ByteHelpers.ToHex(scalar.ToBytes()));
         return;
     }
     throw new ArgumentException($"No valid {nameof(Scalar)}.", nameof(value));
 }
Пример #9
0
        private string GetCacheEntryKey(string path, object model)
        {
            var json   = JsonConvert.SerializeObject(model, JsonSerializationOptions.Default.Settings);
            var rawKey = string.Join(":", path, json);

            using var sha256Hash = SHA256.Create();
            var bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawKey));

            return("arena-request-cache-key: " + ByteHelpers.ToHex(bytes));
        }
Пример #10
0
        public static async Task <AliceClient> CreateNewAsync(Network network, BitcoinAddress changeOutput, byte[] blindedData, IEnumerable <InputProofModel> inputs, Uri baseUri, IPEndPoint torSocks5EndPoint = null)
        {
            var request = new InputsRequest
            {
                BlindedOutputScriptHex = ByteHelpers.ToHex(blindedData),
                ChangeOutputAddress    = changeOutput.ToString(),
                Inputs = inputs
            };

            return(await CreateNewAsync(network, request, baseUri, torSocks5EndPoint));
        }
Пример #11
0
        public async Task <InputsResponse> PostInputsAsync(Script changeOutput, byte[] blindedData, params InputProofModel[] inputs)
        {
            var request = new InputsRequest
            {
                BlindedOutputScriptHex = ByteHelpers.ToHex(blindedData),
                ChangeOutputScript     = changeOutput.ToString(),
                Inputs = inputs
            };

            return(await PostInputsAsync(request));
        }
Пример #12
0
        public void CanEncodeDecodeBlinding()
        {
            var key = new BlindingRsaKey();

            byte[] message     = Encoding.UTF8.GetBytes("áéóúősing me please~!@#$%^&*())_+");
            byte[] blindedData = key.PubKey.Blind(message).BlindedData;
            string encoded     = ByteHelpers.ToHex(blindedData);

            byte[] decoded = ByteHelpers.FromHex(encoded);
            Assert.Equal(blindedData, decoded);
        }
 public string ToHex(bool xhhSyntax = false)
 {
     if (xhhSyntax)
     {
         return($"X'{ByteHelpers.ToHex(ToByte())}'");
     }
     else
     {
         return(ByteHelpers.ToHex(ToByte()));
     }
 }
Пример #14
0
        public void EvenOddSerialization()
        {
            var hexG    = "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798";
            var hexGodd = "0379BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798";

            Assert.Equal(hexG, ByteHelpers.ToHex(Generators.G.ToBytes()));
            Assert.Equal(Generators.G, GroupElement.FromBytes(ByteHelpers.FromHex(hexG)));

            Assert.Equal(hexGodd, ByteHelpers.ToHex(Generators.G.Negate().ToBytes()));
            Assert.Equal(Generators.G.Negate(), GroupElement.FromBytes(ByteHelpers.FromHex(hexGodd)));
        }
Пример #15
0
        public static string HashOutpoints(IEnumerable <OutPoint> outPoints)
        {
            var sb = new StringBuilder();

            foreach (OutPoint input in outPoints.OrderBy(x => x.Hash.ToString()).ThenBy(x => x.N))
            {
                sb.Append(ByteHelpers.ToHex(input.ToBytes()));
            }

            return(HashHelpers.GenerateSha256Hash(sb.ToString()));
        }
Пример #16
0
        private static void CreateDigests()
        {
            var tempDir = "DigestTempDir";

            IoHelpers.DeleteRecursivelyWithMagicDustAsync(tempDir).GetAwaiter();
            Directory.CreateDirectory(tempDir);

            var    torDaemonsDir = Path.Combine(LibraryProjectDirectory, "TorDaemons");
            string torWinZip     = Path.Combine(torDaemonsDir, "tor-win32.zip");

            IoHelpers.BetterExtractZipToDirectoryAsync(torWinZip, tempDir).GetAwaiter();
            File.Move(Path.Combine(tempDir, "Tor", "tor.exe"), Path.Combine(tempDir, "TorWin"));

            string torLinuxZip = Path.Combine(torDaemonsDir, "tor-linux64.zip");

            IoHelpers.BetterExtractZipToDirectoryAsync(torLinuxZip, tempDir).GetAwaiter();
            File.Move(Path.Combine(tempDir, "Tor", "tor"), Path.Combine(tempDir, "TorLin"));

            string torOsxZip = Path.Combine(torDaemonsDir, "tor-osx64.zip");

            IoHelpers.BetterExtractZipToDirectoryAsync(torOsxZip, tempDir).GetAwaiter();
            File.Move(Path.Combine(tempDir, "Tor", "tor"), Path.Combine(tempDir, "TorOsx"));

            string hwiSoftwareDir = Path.Combine(LibraryProjectDirectory, "Hwi", "Software");
            string hwiWinZip      = Path.Combine(hwiSoftwareDir, "hwi-win64.zip");

            IoHelpers.BetterExtractZipToDirectoryAsync(hwiWinZip, tempDir).GetAwaiter();
            File.Move(Path.Combine(tempDir, "hwi.exe"), Path.Combine(tempDir, "HwiWin"));

            string hwiLinuxZip = Path.Combine(hwiSoftwareDir, "hwi-linux64.zip");

            IoHelpers.BetterExtractZipToDirectoryAsync(hwiLinuxZip, tempDir).GetAwaiter();
            File.Move(Path.Combine(tempDir, "hwi"), Path.Combine(tempDir, "HwiLin"));

            string hwiOsxZip = Path.Combine(hwiSoftwareDir, "hwi-osx64.zip");

            IoHelpers.BetterExtractZipToDirectoryAsync(hwiOsxZip, tempDir).GetAwaiter();
            File.Move(Path.Combine(tempDir, "hwi"), Path.Combine(tempDir, "HwiOsx"));

            var tempDirInfo = new DirectoryInfo(tempDir);
            var binaries    = tempDirInfo.GetFiles();

            Console.WriteLine("Digests:");
            foreach (var file in binaries)
            {
                var filePath = file.FullName;
                var hash     = ByteHelpers.ToHex(IoHelpers.GetHashFile(filePath)).ToLowerInvariant();
                Console.WriteLine($"{file.Name} : {hash}");
            }

            IoHelpers.DeleteRecursivelyWithMagicDustAsync(tempDir).GetAwaiter();
        }
    /// <inheritdoc />
    public override object ReadJson(JsonReader reader, Type?objectType, object?existingValue, JsonSerializer?serializer)
    {
        JArray arr = JArray.Load(reader);

        var carr = ToFixedLengthByteArray(StringToBigInteger(arr[0].Value <string>()));
        var sarr = ToFixedLengthByteArray(StringToBigInteger(arr[1].Value <string>()));

        var signatureBytes = carr.Concat(sarr).ToArray();
        var signature      = ByteHelpers.ToHex(signatureBytes);

        var sig = UnblindedSignature.Parse(signature);

        return(sig);
    }
Пример #18
0
        public async Task PostOutputAsync(string roundHash, BitcoinAddress activeOutputAddress, byte[] unblindedSignature)
        {
            var request = new OutputRequest {
                OutputAddress = activeOutputAddress.ToString(), SignatureHex = ByteHelpers.ToHex(unblindedSignature)
            };

            using (var response = await TorClient.SendAsync(HttpMethod.Post, $"/api/v{Helpers.Constants.BackendMajorVersion}/btc/chaumiancoinjoin/output?roundHash={roundHash}", request.ToHttpStringContent()))
            {
                if (response.StatusCode != HttpStatusCode.NoContent)
                {
                    await response.ThrowRequestExceptionFromContentAsync();
                }
            }
        }
Пример #19
0
        public override void FromBytes(byte[] bytes)
        {
            Guard.NotNullOrEmpty(nameof(bytes), bytes);

            foreach (var b in bytes)
            {
                if (b != MethodField.NoAuthenticationRequired && b != MethodField.UsernamePassword)
                {
                    throw new FormatException($"Unrecognized authentication method: {ByteHelpers.ToHex(b)}.");
                }
            }

            Bytes = bytes;
        }
Пример #20
0
        public async Task AuthenticateAsync(CancellationToken ctsToken)
        {
            string authString = "\"\"";

            if (_authenticationToken != null)
            {
                authString = ByteHelpers.ToHex(_authenticationToken);
            }
            else if (_cookieFilePath != null && _cookieFilePath != "")
            {
                authString = ByteHelpers.ToHex(File.ReadAllBytes(_cookieFilePath));
            }
            await SendCommandAsync($"AUTHENTICATE {authString}", initAuthDispose : false, ctsToken : ctsToken).ConfigureAwait(false);
        }
Пример #21
0
		public string ToLine()
		{
			var builder = new StringBuilder();
			builder.Append(BlockHash);
			if(Filter != null) // bech found here
			{
				builder.Append(":");
				builder.Append(Filter.N);
				builder.Append(":");
				builder.Append(Filter.Data.Length);
				builder.Append(":");
				builder.Append(ByteHelpers.ToHex(Filter.Data.ToByteArray()));
			}

			return builder.ToString();
		}
Пример #22
0
        public async Task PostOutputAsync(string roundHash, BitcoinAddress activeOutputAddress, byte[] unblindedSignature)
        {
            var request = new OutputRequest()
            {
                OutputAddress = activeOutputAddress.ToString(), SignatureHex = ByteHelpers.ToHex(unblindedSignature)
            };

            using (var response = await TorClient.SendAsync(HttpMethod.Post, $"/api/v1/btc/chaumiancoinjoin/output?roundHash={roundHash}", request.ToHttpStringContent()))
            {
                if (response.StatusCode != HttpStatusCode.NoContent)
                {
                    string error = await response.Content.ReadAsJsonAsync <string>();

                    var errorMessage = error == null ? string.Empty : $"\n{error}";
                    throw new HttpRequestException($"{response.StatusCode.ToReasonString()}{errorMessage}");
                }
            }
        }
Пример #23
0
    public void SignatureTest()
    {
        // Get a compressed private key.
        string        base58        = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw";
        BitcoinSecret bitcoinSecret = Network.Main.CreateBitcoinSecret(base58);
        Key           privateKey    = bitcoinSecret.PrivateKey;

        Assert.True(privateKey.IsCompressed);

        uint256          hashMsg          = Hashes.DoubleSHA256(Encoding.ASCII.GetBytes("compact hashing test"));
        CompactSignature compactSignature = privateKey.SignCompact(hashMsg);

        Assert.NotNull(compactSignature);

        byte[] sigBytes = CompactSignatureJsonConverter.ToBytes(compactSignature);
        string hex      = ByteHelpers.ToHex(sigBytes);

        Assert.Equal("1F71932FFF735FA6A57787191A296717F71270B2B7E1D90008B7147117F250DBDE012359EED51D28682B1AAB686A8FD8A411A8D07F1EB4D7CDAC5B7EBE73F260A0", hex);
    }
Пример #24
0
		private async Task ReorgOneAsync()
		{
			// 1. Rollback index
			using (await IndexLock.LockAsync())
			{
				Logger.LogInfo($"REORG invalid block: {Index.Last().BlockHash}");
				Index.RemoveLast();
			}

			// 2. Serialize Index. (Remove last line.)
			var lines = await File.ReadAllLinesAsync(IndexFilePath);
			await File.WriteAllLinesAsync(IndexFilePath, lines.Take(lines.Length - 1).ToArray());

			// 3. Rollback Bech32UtxoSet
			if (Bech32UtxoSetHistory.Count != 0)
			{
				Bech32UtxoSetHistory.Last().Rollback(Bech32UtxoSet); // The Bech32UtxoSet MUST be recovered to its previous state.
				Bech32UtxoSetHistory.RemoveLast();

				// 4. Serialize Bech32UtxoSet.
				await File.WriteAllLinesAsync(Bech32UtxoSetFilePath, Bech32UtxoSet
					.Select(entry => entry.Key.Hash + ":" + entry.Key.N + ":" + ByteHelpers.ToHex(entry.Value.ToCompressedBytes())));
			}
		}
Пример #25
0
        public void Synchronize()
        {
            Interlocked.Exchange(ref _running, 1);

            Task.Run(async() =>
            {
                try
                {
                    var blockCount = await RpcClient.GetBlockCountAsync();
                    var isIIB      = true;                // Initial Index Building phase

                    while (IsRunning)
                    {
                        try
                        {
                            // If stop was requested return.
                            if (IsRunning == false)
                            {
                                return;
                            }

                            Height height    = StartingHeight;
                            uint256 prevHash = null;
                            using (await IndexLock.LockAsync())
                            {
                                if (Index.Count != 0)
                                {
                                    var lastIndex = Index.Last();
                                    height        = lastIndex.BlockHeight + 1;
                                    prevHash      = lastIndex.BlockHash;
                                }
                            }

                            if (blockCount - height <= 100)
                            {
                                isIIB = false;
                            }

                            Block block = null;
                            try
                            {
                                block = await RpcClient.GetBlockAsync(height);
                            }
                            catch (RPCException)                             // if the block didn't come yet
                            {
                                await Task.Delay(1000);
                                continue;
                            }

                            if (blockCount - height <= 2)
                            {
                                NewBlock?.Invoke(this, block);
                            }

                            if (!(prevHash is null))
                            {
                                // In case of reorg:
                                if (prevHash != block.Header.HashPrevBlock && !isIIB)                                 // There is no reorg in IIB
                                {
                                    Logger.LogInfo <IndexBuilderService>($"REORG Invalid Block: {prevHash}");
                                    // 1. Rollback index
                                    using (await IndexLock.LockAsync())
                                    {
                                        Index.RemoveLast();
                                    }

                                    // 2. Serialize Index. (Remove last line.)
                                    var lines = File.ReadAllLines(IndexFilePath);
                                    File.WriteAllLines(IndexFilePath, lines.Take(lines.Length - 1).ToArray());

                                    // 3. Rollback Bech32UtxoSet
                                    if (Bech32UtxoSetHistory.Count != 0)
                                    {
                                        Bech32UtxoSetHistory.Last().Rollback(Bech32UtxoSet);                                         // The Bech32UtxoSet MUST be recovered to its previous state.
                                        Bech32UtxoSetHistory.RemoveLast();

                                        // 4. Serialize Bech32UtxoSet.
                                        await File.WriteAllLinesAsync(Bech32UtxoSetFilePath, Bech32UtxoSet
                                                                      .Select(entry => entry.Key.Hash + ":" + entry.Key.N + ":" + ByteHelpers.ToHex(entry.Value.ToCompressedBytes())));
                                    }

                                    // 5. Skip the current block.
                                    continue;
                                }
                            }

                            if (!isIIB)
                            {
                                if (Bech32UtxoSetHistory.Count >= 100)
                                {
                                    Bech32UtxoSetHistory.RemoveFirst();
                                }
                                Bech32UtxoSetHistory.Add(new ActionHistoryHelper());
                            }

                            var scripts = new HashSet <Script>();

                            foreach (var tx in block.Transactions)
                            {
                                // If stop was requested return.
                                // Because this tx iteration can take even minutes
                                // It doesn't need to be accessed with a thread safe fasion with Interlocked through IsRunning, this may have some performance benefit
                                if (_running != 1)
                                {
                                    return;
                                }

                                for (int i = 0; i < tx.Outputs.Count; i++)
                                {
                                    var output = tx.Outputs[i];
                                    if (!output.ScriptPubKey.IsPayToScriptHash && output.ScriptPubKey.IsWitness)
                                    {
                                        var outpoint = new OutPoint(tx.GetHash(), i);
                                        Bech32UtxoSet.Add(outpoint, output.ScriptPubKey);
                                        if (!isIIB)
                                        {
                                            Bech32UtxoSetHistory.Last().StoreAction(ActionHistoryHelper.Operation.Add, outpoint, output.ScriptPubKey);
                                        }
                                        scripts.Add(output.ScriptPubKey);
                                    }
                                }

                                foreach (var input in tx.Inputs)
                                {
                                    OutPoint prevOut = input.PrevOut;
                                    if (Bech32UtxoSet.TryGetValue(prevOut, out Script foundScript))
                                    {
                                        Bech32UtxoSet.Remove(prevOut);
                                        if (!isIIB)
                                        {
                                            Bech32UtxoSetHistory.Last().StoreAction(ActionHistoryHelper.Operation.Remove, prevOut, foundScript);
                                        }
                                        scripts.Add(foundScript);
                                    }
                                }
                            }

                            GolombRiceFilter filter = null;
                            if (scripts.Count != 0)
                            {
                                filter = new GolombRiceFilterBuilder()
                                         .SetKey(block.GetHash())
                                         .SetP(20)
                                         .SetM(1 << 20)
                                         .AddEntries(scripts.Select(x => x.ToCompressedBytes()))
                                         .Build();
                            }

                            var filterModel = new FilterModel
                            {
                                BlockHash   = block.GetHash(),
                                BlockHeight = height,
                                Filter      = filter
                            };

                            await File.AppendAllLinesAsync(IndexFilePath, new[] { filterModel.ToLine() });
                            using (await IndexLock.LockAsync())
                            {
                                Index.Add(filterModel);
                            }
                            if (File.Exists(Bech32UtxoSetFilePath))
                            {
                                File.Delete(Bech32UtxoSetFilePath);
                            }
                            await File.WriteAllLinesAsync(Bech32UtxoSetFilePath, Bech32UtxoSet
                                                          .Select(entry => entry.Key.Hash + ":" + entry.Key.N + ":" + ByteHelpers.ToHex(entry.Value.ToCompressedBytes())));

                            // If not close to the tip, just log debug.
                            // Use height.Value instead of simply height, because it cannot be negative height.
                            if (blockCount - height.Value <= 3 || height % 100 == 0)
                            {
                                Logger.LogInfo <IndexBuilderService>($"Created filter for block: {height}.");
                            }
                            else
                            {
                                Logger.LogDebug <IndexBuilderService>($"Created filter for block: {height}.");
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.LogDebug <IndexBuilderService>(ex);
                        }
                    }
                }
                finally
                {
                    if (IsStopping)
                    {
                        Interlocked.Exchange(ref _running, 3);
                    }
                }
            });
        }
Пример #26
0
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var bytes = ((OwnershipProof)value).ToBytes();

        writer.WriteValue(ByteHelpers.ToHex(bytes));
    }
Пример #27
0
        private async Task TryRegisterCoinsAsync(CcjClientRound inputRegistrableRound)
        {
            try
            {
                List <(uint256 txid, uint index)> registrableCoins = State.GetRegistrableCoins(
                    inputRegistrableRound.State.MaximumInputCountPerPeer,
                    inputRegistrableRound.State.Denomination,
                    inputRegistrableRound.State.FeePerInputs,
                    inputRegistrableRound.State.FeePerOutputs).ToList();

                if (registrableCoins.Any())
                {
                    BitcoinAddress changeAddress = null;
                    BitcoinAddress activeAddress = null;
                    lock (CustomChangeAddressesLock)
                    {
                        if (CustomChangeAddresses.Count > 0)
                        {
                            changeAddress = CustomChangeAddresses.First();
                            CustomChangeAddresses.RemoveFirst();
                        }
                    }
                    lock (CustomActiveAddressesLock)
                    {
                        if (CustomActiveAddresses.Count > 0)
                        {
                            activeAddress = CustomActiveAddresses.First();
                            CustomActiveAddresses.RemoveFirst();
                        }
                    }

                    if (changeAddress is null || activeAddress is null)
                    {
                        IEnumerable <HdPubKey> allUnusedInternalKeys = KeyManager.GetKeys(keyState: null, isInternal: true).Where(x => x.KeyState != KeyState.Used);

                        if (changeAddress is null)
                        {
                            string changeLabel = "ZeroLink Change";
                            IEnumerable <HdPubKey> allChangeKeys = allUnusedInternalKeys.Where(x => x.Label == changeLabel);
                            HdPubKey changeKey = null;

                            KeyManager.AssertLockedInternalKeysIndexed(14);
                            IEnumerable <HdPubKey> internalNotCachedLockedKeys = KeyManager.GetKeys(KeyState.Locked, isInternal: true).Except(AccessCache.Keys);

                            if (allChangeKeys.Count() >= 7 || !internalNotCachedLockedKeys.Any())                             // Then don't generate new keys, because it'd bloat the wallet.
                            {
                                // Find the first one that we did not try to register in the current session.
                                changeKey = allChangeKeys.FirstOrDefault(x => !AccessCache.ContainsKey(x));
                                // If there is no such a key, then use the oldest.
                                if (changeKey == default)
                                {
                                    changeKey = AccessCache.Where(x => allChangeKeys.Contains(x.Key)).OrderBy(x => x.Value).First().Key;
                                }
                                changeKey.SetLabel(changeLabel);
                                changeKey.SetKeyState(KeyState.Locked);
                            }
                            else
                            {
                                changeKey = internalNotCachedLockedKeys.RandomElement();
                                changeKey.SetLabel(changeLabel);
                            }
                            changeAddress = changeKey.GetP2wpkhAddress(Network);
                            AccessCache.AddOrReplace(changeKey, DateTimeOffset.UtcNow);
                        }

                        if (activeAddress is null)
                        {
                            string activeLabel = "ZeroLink Mixed Coin";
                            IEnumerable <HdPubKey> allActiveKeys = allUnusedInternalKeys.Where(x => x.Label == activeLabel);
                            HdPubKey activeKey = null;

                            KeyManager.AssertLockedInternalKeysIndexed(14);
                            IEnumerable <HdPubKey> internalNotCachedLockedKeys = KeyManager.GetKeys(KeyState.Locked, isInternal: true).Except(AccessCache.Keys);

                            if (allActiveKeys.Count() >= 7 || !internalNotCachedLockedKeys.Any())                             // Then don't generate new keys, because it'd bloat the wallet.
                            {
                                // Find the first one that we did not try to register in the current session.
                                activeKey = allActiveKeys.FirstOrDefault(x => !AccessCache.ContainsKey(x));
                                // If there is no such a key, then use the oldest.
                                if (activeKey == default)
                                {
                                    activeKey = AccessCache.Where(x => allActiveKeys.Contains(x.Key)).OrderBy(x => x.Value).First().Key;
                                }
                                activeKey.SetLabel(activeLabel);
                                activeKey.SetKeyState(KeyState.Locked);
                                activeAddress = activeKey.GetP2wpkhAddress(Network);
                            }
                            else
                            {
                                activeKey = internalNotCachedLockedKeys.RandomElement();
                                activeKey.SetLabel(activeLabel);
                            }
                            activeAddress = activeKey.GetP2wpkhAddress(Network);
                            AccessCache.AddOrReplace(activeKey, DateTimeOffset.UtcNow);
                        }
                    }

                    KeyManager.ToFile();

                    var blind = CoordinatorPubKey.Blind(activeAddress.ScriptPubKey.ToBytes());

                    var inputProofs = new List <InputProofModel>();
                    foreach ((uint256 txid, uint index)coinReference in registrableCoins)
                    {
                        SmartCoin coin = State.GetSingleOrDefaultFromWaitingList(coinReference);
                        if (coin is null)
                        {
                            throw new NotSupportedException("This is impossible.");
                        }
                        coin.Secret = coin.Secret ?? KeyManager.GetSecrets(OnePiece, coin.ScriptPubKey).Single();
                        var inputProof = new InputProofModel
                        {
                            Input = coin.GetTxoRef(),
                            Proof = coin.Secret.PrivateKey.SignMessage(ByteHelpers.ToHex(blind.BlindedData))
                        };
                        inputProofs.Add(inputProof);
                    }
                    AliceClient aliceClient = await AliceClient.CreateNewAsync(Network, changeAddress, blind.BlindedData, inputProofs, CcjHostUri, TorSocks5EndPoint);

                    byte[] unblindedSignature = CoordinatorPubKey.UnblindSignature(aliceClient.BlindedOutputSignature, blind.BlindingFactor);

                    if (!CoordinatorPubKey.Verify(unblindedSignature, activeAddress.ScriptPubKey.ToBytes()))
                    {
                        throw new NotSupportedException("Coordinator did not sign the blinded output properly.");
                    }

                    CcjClientRound roundRegistered = State.GetSingleOrDefaultRound(aliceClient.RoundId);
                    if (roundRegistered is null)
                    {
                        // If our SatoshiClient doesn't yet know about the round because of the dealy create it.
                        // Make its state as it'd be the same as our assumed round was, except the roundId and registeredPeerCount, it'll be updated later.
                        roundRegistered = new CcjClientRound(CcjRunningRoundState.CloneExcept(inputRegistrableRound.State, aliceClient.RoundId, registeredPeerCount: 1));
                        State.AddOrReplaceRound(roundRegistered);
                    }

                    foreach ((uint256 txid, uint index)coinReference in registrableCoins)
                    {
                        var coin = State.GetSingleOrDefaultFromWaitingList(coinReference);
                        if (coin is null)
                        {
                            throw new NotSupportedException("This is impossible.");
                        }
                        roundRegistered.CoinsRegistered.Add(coin);
                        State.RemoveCoinFromWaitingList(coin);
                    }
                    roundRegistered.ActiveOutputAddress = activeAddress;
                    roundRegistered.ChangeOutputAddress = changeAddress;
                    roundRegistered.UnblindedSignature  = unblindedSignature;
                    roundRegistered.AliceClient         = aliceClient;
                }
            }
            catch (Exception ex)
            {
                Logger.LogError <CcjClient>(ex);
            }
        }
Пример #28
0
 public void GeneratorsArentChanged()
 {
     Assert.Equal("0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", ByteHelpers.ToHex(Generators.G.ToBytes()));
     Assert.Equal("03AB8F46084B4FA0FC8261328A5A71AF267B1D1F8FE229C63C751D02A2E996E0EC", ByteHelpers.ToHex(Generators.Ga.ToBytes()));
     Assert.Equal("02FB8868ACD9CBBD68964BAA1CFA6B893A6269E01569183474E6C1C4242A0071A9", ByteHelpers.ToHex(Generators.Gg.ToBytes()));
     Assert.Equal("023D11E10CE7A8C17671ED777886FC2B84E65A532FA0C411ABBE96E1206F9DFF80", ByteHelpers.ToHex(Generators.Gh.ToBytes()));
     Assert.Equal("031E7775ED62B79E9E83366198CFE69DFE7408AFF10C331CEE3B2C7F7A5F2EB0C8", ByteHelpers.ToHex(Generators.Gs.ToBytes()));
     Assert.Equal("03665E9B8468DCEDA16ED3E315FBD0A0E597F4AA3B4C6F2146437F53F3AF204C2C", ByteHelpers.ToHex(Generators.GV.ToBytes()));
     Assert.Equal("02B4DF49B623A8A0B245CCF2867134A5DAC12FE39ECEC08B3D361801D2C79DDC14", ByteHelpers.ToHex(Generators.Gw.ToBytes()));
     Assert.Equal("03F50265578FCE5E977162E662ED75D7224AE720FA79B72CF2B6FB86B2136E3B48", ByteHelpers.ToHex(Generators.Gwp.ToBytes()));
     Assert.Equal("02E33C9F3CBE6388A2D3C3ECB12153DB73499928541905D86AAA4FFC01F2763B54", ByteHelpers.ToHex(Generators.Gx0.ToBytes()));
     Assert.Equal("0246253CC926AAB789BAA278AB9A54EDEF455CA2014038E9F84DE312C05A8121CC", ByteHelpers.ToHex(Generators.Gx1.ToBytes()));
 }
Пример #29
0
 public static string ToHex(this IBitcoinSerializable me)
 {
     return(ByteHelpers.ToHex(me.ToBytes()));
 }
Пример #30
0
        public void Synchronize()
        {
            Interlocked.Exchange(ref _running, 1);

            Task.Run(async() =>
            {
                try
                {
                    var blockCount = await RpcClient.GetBlockCountAsync();
                    var isIIB      = true;                // Initial Index Building phase

                    while (IsRunning)
                    {
                        try
                        {
                            // If stop was requested return.
                            if (IsRunning == false)
                            {
                                return;
                            }

                            var height       = StartingHeight;
                            uint256 prevHash = null;
                            using (await IndexLock.LockAsync())
                            {
                                if (Index.Count != 0)
                                {
                                    var lastIndex = Index.Last();
                                    height        = lastIndex.BlockHeight + 1;
                                    prevHash      = lastIndex.BlockHash;
                                }
                            }

                            if (blockCount - (int)height <= 100)
                            {
                                isIIB = false;
                            }

                            Block block = null;
                            try
                            {
                                block = await RpcClient.GetBlockAsync(height);
                            }
                            catch (RPCException)                             // if the block didn't come yet
                            {
                                await Task.Delay(1000);
                                continue;
                            }

                            if (prevHash != null)
                            {
                                // In case of reorg:
                                if (prevHash != block.Header.HashPrevBlock && !isIIB)                                 // There is no reorg in IIB
                                {
                                    Logger.LogInfo <IndexBuilderService>($"REORG Invalid Block: {prevHash}");
                                    // 1. Rollback index
                                    using (await IndexLock.LockAsync())
                                    {
                                        Index.RemoveLast();
                                    }

                                    // 2. Serialize Index. (Remove last line.)
                                    var lines = File.ReadAllLines(IndexFilePath);
                                    File.WriteAllLines(IndexFilePath, lines.Take(lines.Length - 1).ToArray());

                                    // 3. Rollback Bech32UtxoSet
                                    if (Bech32UtxoSetHistory.Count != 0)
                                    {
                                        Bech32UtxoSetHistory.Last().Rollback(Bech32UtxoSet);                                         // The Bech32UtxoSet MUST be recovered to its previous state.
                                        Bech32UtxoSetHistory.RemoveLast();

                                        // 4. Serialize Bech32UtxoSet.
                                        await File.WriteAllLinesAsync(Bech32UtxoSetFilePath, Bech32UtxoSet
                                                                      .Select(entry => entry.Key.Hash + ":" + entry.Key.N + ":" + ByteHelpers.ToHex(entry.Value.ToCompressedBytes())));
                                    }

                                    // 5. Skip the current block.
                                    continue;
                                }
                            }

                            if (!isIIB)
                            {
                                if (Bech32UtxoSetHistory.Count >= 100)
                                {
                                    Bech32UtxoSetHistory.RemoveFirst();
                                }
                                Bech32UtxoSetHistory.Add(new ActionHistoryHelper());
                            }

                            var scripts = new HashSet <Script>();

                            foreach (var tx in block.Transactions)
                            {
                                for (int i = 0; i < tx.Outputs.Count; i++)
                                {
                                    var output = tx.Outputs[i];
                                    if (!output.ScriptPubKey.IsPayToScriptHash && output.ScriptPubKey.IsWitness)
                                    {
                                        var outpoint = new OutPoint(tx.GetHash(), i);
                                        Bech32UtxoSet.Add(outpoint, output.ScriptPubKey);
                                        if (!isIIB)
                                        {
                                            Bech32UtxoSetHistory.Last().StoreAction(ActionHistoryHelper.Operation.Add, outpoint, output.ScriptPubKey);
                                        }
                                        scripts.Add(output.ScriptPubKey);
                                    }
                                }

                                foreach (var input in tx.Inputs)
                                {
                                    var found = Bech32UtxoSet.SingleOrDefault(x => x.Key == input.PrevOut);
                                    if (found.Key != default)
                                    {
                                        Script val = Bech32UtxoSet[input.PrevOut];
                                        Bech32UtxoSet.Remove(input.PrevOut);
                                        if (!isIIB)
                                        {
                                            Bech32UtxoSetHistory.Last().StoreAction(ActionHistoryHelper.Operation.Remove, input.PrevOut, val);
                                        }
                                        scripts.Add(found.Value);
                                    }
                                }
                            }

                            // https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki
                            // The parameter k MUST be set to the first 16 bytes of the hash of the block for which the filter
                            // is constructed.This ensures the key is deterministic while still varying from block to block.
                            var key = block.GetHash().ToBytes().Take(16).ToArray();

                            GolombRiceFilter filter = null;
                            if (scripts.Count != 0)
                            {
                                filter = GolombRiceFilter.Build(key, scripts.Select(x => x.ToCompressedBytes()));
                            }

                            var filterModel = new FilterModel
                            {
                                BlockHash   = block.GetHash(),
                                BlockHeight = height,
                                Filter      = filter
                            };

                            await File.AppendAllLinesAsync(IndexFilePath, new[] { filterModel.ToLine() });
                            using (await IndexLock.LockAsync())
                            {
                                Index.Add(filterModel);
                            }
                            if (File.Exists(Bech32UtxoSetFilePath))
                            {
                                File.Delete(Bech32UtxoSetFilePath);
                            }
                            await File.WriteAllLinesAsync(Bech32UtxoSetFilePath, Bech32UtxoSet
                                                          .Select(entry => entry.Key.Hash + ":" + entry.Key.N + ":" + ByteHelpers.ToHex(entry.Value.ToCompressedBytes())));

                            if (blockCount - height <= 3 || height % 100 == 0)                             // If not close to the tip, just log debug.
                            {
                                Logger.LogInfo <IndexBuilderService>($"Created filter for block: {height}.");
                            }
                            else
                            {
                                Logger.LogDebug <IndexBuilderService>($"Created filter for block: {height}.");
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.LogDebug <IndexBuilderService>(ex);
                        }
                    }
                }
                finally
                {
                    if (IsStopping)
                    {
                        Interlocked.Exchange(ref _running, 3);
                    }
                }
            });
        }