/// <inheritdoc /> public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var epk = (ExtPubKey)value; var hex = ByteHelpers.ToHex(epk.ToBytes()); writer.WriteValue(hex); }
public static string GenerateSha256Hash(string input) { using var sha256 = SHA256.Create(); var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(input)); return(ByteHelpers.ToHex(hash)); }
/// <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); }
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); }
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()); }
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)); }
/// <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)); }
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)); }
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)); }
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)); }
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())); } }
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))); }
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())); }
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); }
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(); } } }
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; }
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); }
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(); }
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}"); } } }
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); }
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()))); } }
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); } } }); }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var bytes = ((OwnershipProof)value).ToBytes(); writer.WriteValue(ByteHelpers.ToHex(bytes)); }
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); } }
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())); }
public static string ToHex(this IBitcoinSerializable me) { return(ByteHelpers.ToHex(me.ToBytes())); }
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); } } }); }