Автор Marozka
Статья написана для Конкурса статей #10
Для старта работы необходимо скачать с сайта не реклама последнюю версию адресов такого формата, 1111111111111111111114oLvT2 без баланса
В этой базе все известные биткоин адреса с балансом.
И переименовать файл в addresses.txt или изменить имя файла в строчке номер 13 кода программы
После чего программа отсортирует кошельки из базы по видам и сохранит.
Что существенно ускоряет работу программы.
После чего проверять вашу удачу.
Код представляет собой консольное приложение на C# для генерации и проверки биткоин-адресов и соответствующих им приватных ключей. Приложение использует библиотеку NBitcoin для работы с биткоин-адресами и ключами. Оно также поддерживает многопоточность и сохранение состояния между запусками. Вот подробное описание основных компонентов и функций кода.
Основные Константы
Статические Переменные
Основные Методы
Статья написана для Конкурса статей #10
Для старта работы необходимо скачать с сайта не реклама последнюю версию адресов такого формата, 1111111111111111111114oLvT2 без баланса
В этой базе все известные биткоин адреса с балансом.
И переименовать файл в addresses.txt или изменить имя файла в строчке номер 13 кода программы
После чего программа отсортирует кошельки из базы по видам и сохранит.
- Программа автоматически сортирует адреса из базы по типам (P2PKH, P2SH, P2WPKH, P2TR) и сохраняет их в отдельные файлы:
- p2pkh_addresses.txt
- p2sh_addresses.txt
- p2wpkh_addresses.txt
- p2tr_addresses.txt
Что существенно ускоряет работу программы.
После чего проверять вашу удачу.
Код представляет собой консольное приложение на C# для генерации и проверки биткоин-адресов и соответствующих им приватных ключей. Приложение использует библиотеку NBitcoin для работы с биткоин-адресами и ключами. Оно также поддерживает многопоточность и сохранение состояния между запусками. Вот подробное описание основных компонентов и функций кода.
Основные Константы
- StateFilePath: Путь к файлу, где сохраняется состояние приложения (текущая итерация).
- AddressesFilePath: Путь к файлу с исходными адресами для проверки.
- MatchesFilePath: Путь к файлу, куда записываются найденные совпадения.
- P2PKHAddressesFilePath, P2SHAddressesFilePath, P2WPKHAddressesFilePath, P2TRAddressesFilePath: Пути к файлам, куда сортируются адреса по типам.
- GeneratedPrivateKeysFilePath: Путь к файлу, где сохраняются сгенерированные приватные ключи.
Статические Переменные
- generatedPrivateKeysCount: Количество сгенерированных приватных ключей.
- generatedAddressesCount: Количество сгенерированных адресов.
- checkedAddressesCount: Количество проверенных адресов.
- matchesCount: Количество найденных совпадений.
- noMatchesCount: Количество несовпавших адресов.
- lastIteration: Номер последней итерации.
- taskQueue: Очередь задач для асинхронного выполнения.
- generatedPrivateKeys: Хэш-набор для хранения сгенерированных приватных ключей.
Основные Методы
- Main:
- Главный метод, который управляет выполнением программы.
- Проверяет наличие файлов с адресами.
- Загружает состояние и сгенерированные приватные ключи.
- Запускает процесс генерации и проверки ключей.
- Сохраняет состояние и сгенерированные приватные ключи.
- Выводит финальную статистику.
- CheckFilesExist:
- Проверяет наличие файлов с адресами.
- Возвращает true, если все необходимые файлы существуют.
- LoadState:
- Загружает текущую итерацию из файла StateFilePath.
- SaveState:
- Сохраняет текущую итерацию в файл StateFilePath.
- LoadGeneratedPrivateKeys:
- Загружает сгенерированные приватные ключи из файла GeneratedPrivateKeysFilePath.
- SaveGeneratedPrivateKeys:
- Сохраняет сгенерированные приватные ключи в файл GeneratedPrivateKeysFilePath.
- SortAddressesFile:
- Сортирует адреса из исходного файла по типам и записывает их в соответствующие файлы.
- GenerateAndCheckKeysAsync:
- Асинхронно генерирует и проверяет приватные ключи и адреса.
- Определяет количество доступных ядер процессора.
- Создает семафор для ограничения количества одновременно выполняемых задач.
- Запускает периодическое обновление статистики.
- Создает задачи для каждого ядра процессора.
- В каждой задаче:
- Генерирует приватный ключ.
- Проверяет, не был ли этот ключ уже сгенерирован.
- Добавляет ключ в хэш-набор и увеличивает счетчики.
- Генерирует все типы адресов для данного публичного ключа.
- Логирует сгенерированные ключи и адреса.
- Проверяет каждый адрес на совпадение с адресами в соответствующем файле.
- Увеличивает счетчики проверенных адресов и совпадений.
- ShouldStop:
- Определяет, следует ли остановить процесс генерации и проверки.
- Возвращает false (можно изменить условие остановки).
- CheckAddressAsync:
- Асинхронно проверяет, существует ли адрес в файле с адресами.
- Открывает файл с адресами.
- Проверяет каждую строку на совпадение с заданным адресом.
- Если найдено совпадение, увеличивает счетчик совпадений и сохраняет информацию о совпадении.
- Если совпадение не найдено, увеличивает счетчик несовпадений.
- SaveMatch:
- Сохраняет информацию о найденном совпадении в файл MatchesFilePath.
- Log:
- Выводит сообщение в консоль.
- Используется для логирования различных событий.
- PrintStatisticsPeriodically:
- Периодически выводит статистику в консоль.
- Каждые 10 секунд вызывает метод PrintStatistics.
- PrintStatistics:
- Выводит текущую статистику в консоль.
- Очищает консоль и выводит значения всех счетчиков.
Заключение
Программа обеспечивает эффективное и надежное генерирование и проверку биткоин-адресов и приватных ключей. Благодаря использованию многопоточности и оптимизации процесса проверки, она значительно ускоряет работу, особенно при больших объемах данных. Сохранение состояния между запусками позволяет продолжить процесс с места остановки, что делает программу удобной для длительных вычислений.
C#:using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using NBitcoin; class Sorter { private const string StateFilePath = "state.txt"; private const string AddressesFilePath = "addresses.txt"; private const string MatchesFilePath = "matches.txt"; private const string P2PKHAddressesFilePath = "p2pkh_addresses.txt"; private const string P2SHAddressesFilePath = "p2sh_addresses.txt"; private const string P2WPKHAddressesFilePath = "p2wpkh_addresses.txt"; private const string P2TRAddressesFilePath = "p2tr_addresses.txt"; private const string GeneratedPrivateKeysFilePath = "generated_private_keys.txt"; private static int generatedPrivateKeysCount = 0; private static int generatedAddressesCount = 0; private static int checkedAddressesCount = 0; private static int matchesCount = 0; private static int noMatchesCount = 0; private static int lastIteration = 0; private static ConcurrentQueue<Task> taskQueue = new ConcurrentQueue<Task>(); private static HashSet<string> generatedPrivateKeys = new HashSet<string>(); public static async Task Main(string[] args) { if (CheckFilesExist()) { LoadState(); LoadGeneratedPrivateKeys(); await GenerateAndCheckKeysAsync(); } else { SortAddressesFile(); LoadState(); LoadGeneratedPrivateKeys(); await GenerateAndCheckKeysAsync(); } SaveState(); SaveGeneratedPrivateKeys(); PrintStatistics(); // Финальный вывод статистики } private static bool CheckFilesExist() { return File.Exists(P2PKHAddressesFilePath) && File.Exists(P2SHAddressesFilePath) && File.Exists(P2WPKHAddressesFilePath) && File.Exists(P2TRAddressesFilePath); } private static void LoadState() { if (File.Exists(StateFilePath)) { lastIteration = int.Parse(File.ReadAllText(StateFilePath).Trim()); Log($"Loaded state: Iteration {lastIteration}"); } } private static void SaveState() { File.WriteAllText(StateFilePath, lastIteration.ToString().Trim()); Log($"Saved state: Iteration {lastIteration}"); } private static void LoadGeneratedPrivateKeys() { if (File.Exists(GeneratedPrivateKeysFilePath)) { generatedPrivateKeys = new HashSet<string>(File.ReadLines(GeneratedPrivateKeysFilePath)); Log($"Loaded {generatedPrivateKeys.Count} generated private keys."); } } private static void SaveGeneratedPrivateKeys() { File.WriteAllLines(GeneratedPrivateKeysFilePath, generatedPrivateKeys); Log($"Saved {generatedPrivateKeys.Count} generated private keys."); } private static void SortAddressesFile() { if (File.Exists(AddressesFilePath)) { using (var reader = new StreamReader(AddressesFilePath)) { using (var p2pkhWriter = new StreamWriter(P2PKHAddressesFilePath, false)) using (var p2shWriter = new StreamWriter(P2SHAddressesFilePath, false)) using (var p2wpkhWriter = new StreamWriter(P2WPKHAddressesFilePath, false)) using (var p2trWriter = new StreamWriter(P2TRAddressesFilePath, false)) { string line; while ((line = reader.ReadLine()) != null) { switch (line[0]) { case '1': p2pkhWriter.WriteLine(line); break; case '3': p2shWriter.WriteLine(line); break; case 'b': if (line.StartsWith("bc1")) { if (line.Length == 42) p2wpkhWriter.WriteLine(line); else p2trWriter.WriteLine(line); } break; } } } } Log($"Sorted addresses into separate files."); } } private static async Task GenerateAndCheckKeysAsync() { int availableCores = Environment.ProcessorCount; var semaphore = new SemaphoreSlim(availableCores); var cts = new CancellationTokenSource(); var printStatsTask = PrintStatisticsPeriodically(cts.Token); var tasks = new List<Task>(); for (int i = 0; i < availableCores; i++) { tasks.Add(Task.Run(async () => { while (true) { if (taskQueue.TryDequeue(out var task)) { await task; } else { if (ShouldStop()) { break; } Key bitcoinPrivateKey; string privateKeyString; do { bitcoinPrivateKey = new Key(); privateKeyString = bitcoinPrivateKey.GetWif(Network.Main).ToString(); } while (generatedPrivateKeys.Contains(privateKeyString)); generatedPrivateKeys.Add(privateKeyString); generatedPrivateKeysCount++; generatedAddressesCount += 4; // 4 вида адресов var publicKey = bitcoinPrivateKey.PubKey; // Генерация всех видов адресов var p2pkhAddress = publicKey.GetAddress(ScriptPubKeyType.Legacy, Network.Main); // Legacy адрес (начинается с "1") var p2shAddress = publicKey.GetAddress(ScriptPubKeyType.SegwitP2SH, Network.Main); // P2SH-адрес (начинается с "3") var p2wpkhAddress = publicKey.GetAddress(ScriptPubKeyType.Segwit, Network.Main); // SegWit адрес (начинается с "bc1") var p2trAddress = publicKey.GetAddress(ScriptPubKeyType.TaprootBIP86, Network.Main); // Taproot адрес (начинается с "bc1") Log($"Generated key pairs: Private Key: {privateKeyString}, Public Key: {publicKey}"); Log($"P2PKH Address: {p2pkhAddress}"); Log($"P2SH Address: {p2shAddress}"); Log($"P2WPKH Address: {p2wpkhAddress}"); Log($"P2TR Address: {p2trAddress}"); // Параллельная проверка всех адресов var addressesToCheck = new[] { (p2pkhAddress, privateKeyString, bitcoinPrivateKey, P2PKHAddressesFilePath), (p2shAddress, privateKeyString, bitcoinPrivateKey, P2SHAddressesFilePath), (p2wpkhAddress, privateKeyString, bitcoinPrivateKey, P2WPKHAddressesFilePath), (p2trAddress, privateKeyString, bitcoinPrivateKey, P2TRAddressesFilePath) }; var checkTasks = addressesToCheck.Select(async addr => { await semaphore.WaitAsync(); try { await CheckAddressAsync(addr.Item1, addr.Item2, addr.Item3, addr.Item4); } finally { semaphore.Release(); } }).ToList(); await Task.WhenAll(checkTasks); lastIteration++; } } })); } await Task.WhenAll(tasks); cts.Cancel(); // Останавливаем таймер await printStatsTask; // Ждем завершения задачи обновления статистики } private static bool ShouldStop() { // Implement your condition to stop the loop here return false; } private static async Task CheckAddressAsync(BitcoinAddress address, string privateKeyString, Key privateKey, string addressesFilePath) { string addressString = address.ToString(); if (File.Exists(addressesFilePath)) { using (StreamReader reader = new StreamReader(addressesFilePath)) { string line; bool foundMatch = false; while ((line = await reader.ReadLineAsync()) != null) { checkedAddressesCount++; if (line.Trim() == addressString) { matchesCount++; Log($"Match found: Private Key: {privateKeyString}, Generated Address: {address}, Compared with: {line}"); SaveMatch(privateKeyString, address, line); foundMatch = true; break; } } if (!foundMatch) { noMatchesCount++; } } } } private static void SaveMatch(string privateKeyString, BitcoinAddress address, string comparedAddress) { string matchInfo = $"Private Key: {privateKeyString}, Generated Address: {address}, Compared with: {comparedAddress}"; File.AppendAllText(MatchesFilePath, matchInfo + Environment.NewLine); Log($"Match saved: {matchInfo}"); } private static void Log(string message) { Console.WriteLine(message); } private static async Task PrintStatisticsPeriodically(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { PrintStatistics(); await Task.Delay(10000, cancellationToken); } } private static void PrintStatistics() { Console.Clear(); Log($"Сгенерировано приватных ключей: {generatedPrivateKeysCount}"); Log($"Сгенерировано адресов: {generatedAddressesCount}"); Log($"Проверено адресов: {checkedAddressesCount}"); Log($"Совпало: {matchesCount}"); Log($"Не совпало: {noMatchesCount}"); } }
Последнее редактирование модератором: