Халвинг биткоин кэш

Эта страница описывает код ядра Биткойна, который управляет запуском и инициализацией.

Точка входа в программу

Точку входа в программу можно найти в bitcoind.cpp. main () — это три строки кода:

  • SetupEnvironment() (все, что это делает, — это устанавливает локаль программы)
  • Подключение обработчиков сигналов
  • AppInit() (эта функция циклически работает в течение всего срока службы программы)

Аппинит: это находится неподалеку в bitcoind.cpp:

  • Разбирает командную строку
  • Открывает каталог данных
  • Читает конфигурационный файл
  • Разветвляет процесс (если он работает как демон)
  • Передает управление AppInit2(), находящемуся в

    init.cpp.

Шаги инициализации (init.cpp)

AppInit2() инициализирует биткойн-систему.

Он содержит около 800 строк кода, которые разбиты на 12 шагов.

Где начинается каждый шаг, задокументировано в коде. Init.cpp имеет несколько функций в верхней части файла, но по большей части он состоит из AppInit2().

В следующей таблице приведены краткие сведения об этих шагах:

Шаг Инициализации краткое описание Более Длинное Описание
1 Задачи настройки для конкретной операционной системы Эти задачи не особенно интересны.
Дополнительные сведения см. в коде.

2 Взаимодействие Параметров Некоторые параметры командной строки требуют. Чтобы другие параметры были установлены определенным образом.
например,-zapwallettxes подразумевает-rescan. Таким образом. Код установит флаг-rescan=true. Если он еще не установлен.
3 Внутренние флаги /
проверка работоспособности параметров
Для кошелька он проверяет уровень комиссии за транзакцию (убеждается. Что ваша комиссия достаточно высока. Чтобы претендовать на ретрансляцию [ошибка]; но не абсурдно высока [предупреждение]).
4 Приложение init. / RPC-сервер

Блокирует каталог данных. (Если не удается. Распечатайте ошибку и завершите работу.)

Создайте X потоков для механизма проверки скриптов. (По умолчанию=0, что означает использование всех доступных процессоров; boost::thread::hardware_concurrency).
запустите RPC-сервер в режиме

5 Проверка целостности базы данных кошелька Если кошелек включен, попробуйте открыть его.

Если пользователь знает, что кошелек был поврежден (-salvagewallet). Попробуйте восстановить закрытые ключи.

6 Инициализация Сети

Узел регистрирует определенные сигналы.
Проверяет. Хочет ли пользователь взаимодействовать только с одноранговыми узлами в определенной сети (ip4, ip6, tor).

проверяет, следует ли использовать луковую маршрутизацию (tor).
проверяет. Хочет ли пользователь внести в белый список какие-либо конкретные одноранговые узлы.
Попытки прослушивания биткойн-порта (выходы при сбое).
Если пользователь указал определенное одноранговое начальное соединение, попытайтесь подключиться.

7 Загрузите блок-цепь.

Загрузите блокчейн в память и инициализируйте кэш UTXO.

Вычислите размеры кэша.
Существует общий размер кэша, который делится на три конкретных кэша.
Общий размер кэша по умолчанию = 100 МБ (Макс: 4 ГБ, мин: 4 МБ).

1) Блокчейн-кэш: 1/8 от общего объема кэша. Но не должен быть больше 2 МБ.
2) кэш базы данных UTXO : 25-50% от оставшегося пространства кэша. Это кэш LevelDB.
Он хранит несжатые блоки данных LevelDB и управляется LevelDB. Как описано в документации LevelDB.
3) UTXO in-memory cache: половина оставшегося пространства кэша.
Этот размер кэша определяет размер объекта cacheCoins (защищенного члена CoinsViewCache).
TODO: убедитесь, что это утверждение верно…

Загрузите блокчейн в mapBlockIndex.
под
то, что загружается в память, — это объекты CBlockIndex. Которые содержат метаданные о блоке.
Проверка последних 288 блоков (VerifyDB).
Примечание: программа занимает менее 1 секунды от запуска до этого момента; этот шаг занимает около 10-20 секунд.

Набор UTXO.
Набор UTXO не загружается в память; вместо этого кэш будет заполняться по мере доступа к монетам из базы данных.
Обратите внимание. Что по состоянию на май 2015 года для хранения всего набора UTXO в памяти потребуется около 3,6 ГБ,
а по состоянию на январь 2016 года сжатые данные на диске составляют около 1,2 Гб.

8 Загрузите бумажник. Если это первый раз, когда программа была запущена, она создает кошелек и дает вам начальный ключ (адрес).
9 Техническое обслуживание Datadir Если пользователь блокирует обрезку. Снимите флажок NODE_NETWORK и вызовите функцию обрезки.
10 Импорт блоков Сканируйте лучшие цепочки в базе данных блочных цепочек. Которые еще не подключены как активная лучшая цепочка.
11 Start node /
RPC server

Вызывает StartNode in net.cpp
это запускает группу сетевых потоков. Включая ThreadProcessMessage. Которая является основным потоком программы (см. ниже).
Переход RPC-сервера из режима

12 ЗАКОНЧЕННЫЕ

Когда AppInit2 завершается, управление возвращается в AppInit() in bitcoind.cpp.

Там поток верхнего уровня кода бесконечно зацикливается в функции WaitForShutdown(). Он спит в течение 2 секунд и проверяет, нажал ли пользователь ctrl-C. Если это так, то он вызывает функцию Shutdown() обратно init.cpp.

Shutdown() завершает работу сервера RPC, останавливает узел. Отменяет регистрацию обработчиков сигналов и т. д.. А затем программа завершается.

Размеры Кэша

Шаг 7 инициализировал размеры кэша. На шаге 7 предусмотрено 3 тайника. Два из них-это кэши базы данных LevelDB, а другой — кэш монет. Размер которого управляется кодом промывки в main.cpp.

Пользователь может выделить общий размер кэша с помощью-dbcache. Пользователь не может выбрать, сколько места выделить для каждого конкретного кэша. Общий размер кэша по умолчанию = 100 МБ (Макс: 4 ГБ, мин: 4 МБ).

1) кэш блочного индекса

Этот кэш хранит несжатые фрагменты данных /blocks/index LevelDB и управляется LevelDB. Как описано в документации LevelDB.

Если пользователь включает полный индекс транзакции (-txindex=1). Он может составлять до 1/8 от общего размера кэша. Если -txindex не включен. То требуется только 2 MiB.

2) кэш базы данных UTXO

Это кэш LevelDB для базы данных /chainstate.

Этому кэшу выделяется 25-50% оставшегося пространства кэша. В зависимости от общего размера кэша.

3) кэш UTXO в памяти

Это кэш монет, который управляется main.cpp код. (см. раздел FlushStateToDisk и связанные с ним функции)

Переменная (nCoinsCache) объявляется как extern в main.h. В main.cpp, он жестко закодирован до 5000 * 300 (монеты в памяти составляют около 300 байт. Так что это означает 5000 монет). Однако он должен быть повторно инициализирован на шаге 7.

Этому кэшу отводится все оставшееся пространство кэша.

Этот кэш не загружается во время инициализации. А заполняется по мере обращения к монетам. (Это можно проверить с помощью конструктора CCoinsViewCache. Который устанавливает cachedCoinsUsage=0.)

Запуск Потока

Код использует boost::thread_groups для управления различными потоками.

Следует отметить, что хотя Bitcoin Core является многопоточной программой, Комментарий Майка Хирна в BIP 31 (2012)

Имеется в виду. Что подавляющее большинство действий программы происходит в потоке обмена сообщениями (ThreadMessageHandler — см.)

Почти все потоки являются частью одной основной группы потоков. Которая создается в стеке при запуске программы (см. bitcoind.cpp). Эта группа потоков передается init.cpp что создает несколько дочерних потоков (включая несколько потоков проверки скриптов. Но все они являются частью основной группы потоков. А не отдельной группой.)

Группа потоков передается net.cpp, который создает сетевые потоки, включая поток обработки сообщений.

Две другие группы потоков зависят от конкретной задачи:

  • группа потоков сервера rpc (см. rpcserver.h/cpp)
  • группа потоков майнера

Естественно, узел создаст группу потоков сервера RPC только в том случае. Если сервер RPC активирован. И создаст группу потоков майнера только в том случае. Если он занимается майнингом. Если оба они отключены. То Bitcoin Core имеет только одну группу потоков.

Дочерние Потоки

Родительский поток (то есть поток. В котором начинает работать программа) делегирует почти всю работу программы дочерним потокам. После нереста нитей в init.cpp и net.cpp, Родительский поток просто слушает команду завершения работы. В это время родительскому потоку нужно только прервать потоки в своей группе потоков и продолжить завершение работы.

Дочерние потоки суммируются в этой таблице в порядке их создания:

Нитки Когда / Где Создан Описание
Проверка скриптов Шаг 4
init.cpp
Это набор потоков — 4 по умолчанию.
Проверка скриптов (включая проверку сигнатур) стоит дорого, поэтому обрабатывается в отдельных потоках.
Планировщик Шаг 4
init.cpp
Поток планировщика.
(TODO: опишите)
Потоки RPC Шаг 4
rpcserver.cpp
Если сервер RPC включен, запустите группу потоков для обработки вызовов RPC.
Импорт Шаг 10
init.cpp
Импортирует блоки. Три сценария:
1) переиндексация (повторное сканирование всех известных блоков из файлов blk???.dat).
2) Bootstrap (используйте bootstrap.dat в качестве альтернативы полному IBD из сети.)
3) -loadblock (сканируйте конкретный файл blk???.dat)
если ни один из них не применяется. Этот поток ничего не делает.
DNSAddressSeed Шаг 11
net.cpp
Пытается построить вектор IP — адресов на основе семян dns. Сохраняет вектор и выходит из потока.
В тесте в июне 2014 года это заняло около 4 секунд и нашло 158 адресов.
Подключи И Играй Шаг 11
net.cpp
UPNP (Universal Plug & Play)
занимается отображением портов для UPNP.
SocketHandler Шаг 11
net.cpp
Этот поток обслуживает сокеты:
ожидает ввода-вывода на всех соответствующих сокетах с таймаутом 50 мс.
Обрабатывает новые входящие соединения на прослушивающем сокете и создает CNode для нового однорангового узла.

Устанавливает сокеты. Которые ничего не сделали с отключенным состоянием.

OpenAddedConnections Шаг 11
net.cpp
Инициирует исходящие соединения. Указанные пользователем с параметром –addnode.
если не удается подключиться. Спит в течение 2 минут каждый цикл.
OpenConnections Шаг 11
net.cpp
Инициирует другие исходящие соединения из семян DNS (если это не удается. Найдите узлы на основе фиксированных семян)
, Если не удается подключиться. Спит в течение 500 миллисекунд каждый цикл.
MessageHandler Шаг 11
net.cpp
Это основной поток программы.
Этот поток запускает цикл while(true). Получая и отправляя сообщения. (См.net.cpp :1049)
код использует boost::signals2 для вызова функций ProcessMessages и SendMessages в main.cpp.
(код. Вводящий сигналы. Находится в PR 2154 — см. предпоследний коммит в этом pull.)
ProcessMessage и SendMessage запускаются в этом потоке.
Итак, большая часть кода в main.cpp работает в этой теме.
Смыватель Бумажника Шаг 12
init.cpp
Если кошелек включен, этот поток периодически сбрасывает кошелек.

См. также

Bitcoin Core 0.11 (Ch 1): Обзор
Bitcoin Core 0.11 (Ch 2): хранение данных
Bitcoin Core 0.11 (Ch 4): P2P сеть
Bitcoin Core 0.11 (Ch 5): начальная загрузка блока
Bitcoin Core 0.11 (Ch 6): блокчейн