Нынешнее видение по организации сетевого (в т.ч. p2p) модуля

Несколько уровней внутри самого модуля

Для тестирования самое то. Код понятный, кусок логики не придется искать в других директориях. Снизу наверх:

  1. IO уровень: оперирует соединениями, сырыми байтами, реконнектами, таймаутами и асинхронностью (там поллинг самого общего плана)
  2. Peer уровень:
    • протокол и сериализация,
    • коллекция peers,
    • броадкасты,
    • персистентное хранилище, связанное с peers (пусть отдельно будет от хранилища блокчейна),
    • ban/unban
    • Dandelion (да, он здесь, а не в уровне 3)
  3. Integration layer:
    • фильтр и cache (это множество хешей, которые позволят не отправлять TX или блок в узел, у которого он есть, а также не отсылать в другие модули то, что им уже известно)
    • бридж с основной системой, т.е. формирование и трансляция запросов/ответов между ней (API модулей) и уровнем 2
    • межпоточное взаимодействие

Основные моменты подробнее

  1. Один поток на все вышесказанное (сетевая логика, а также уровни 2 и 3)
    • Тут логика, которая не требует вычислений, можно иметь очень много активных соединений, пределом может стать только сеть или память, но не cpu
    • Исключение: может понадобиться отдельный поток, который зипует громоздкие ответы. Пусть они асинхронно формируются по мере надобности в них
    • Взаимодействие с другими потоками или через очереди (если это запросы/ответы) или напрямую (явно сделать, чтоб было понятно, что это константный кусок памяти). Мьютексы ставить на небольшие кусочки обновляемых данных (ну например { total_difficulty, total_height }), которые можно быстро прочитать
    • В очередях только что-то легко копируемое или immutable data, напр. { Type type; shared_ptr и т.п.}
  2. Сетевое хозяйство и протокол
    • Ограничиваемся TCP и IPv4. Потом успеем добавить если что понадобится, а так пусть меньше сначала кода будет
    • В качестве библиотеки по сетевым вещам и асинхронности очень желаю libuv. Обоснование ниже.
    • Можно взять за основу протокол из grin, что-то убрать/добавить проблем не составит
    • Dandelion: надо определиться с одной из 2х схем, прописанных в документации по grin
  3. Peers
    • Логику взять у grin, для начала
    • Для хранилища (не блокчейн, только для peers, оно отдельное должно быть) взять sqlite как наиболее проверенную временем штуку. Она гибкая (индексы и т.д.). Кстати, in-memory sqlite тоже хорошо себя зарекомендовало как штука для работы с табличными данными и сложными индексами. Когда/если будут видны ограничения по performance или станет ясно, что не нужно индексирование, можно быдет подобрать key-value storage побыстрее
  4. Кэши и фильтры
    • То же, что и у grin для начала. Можно будет какой-нибудь bloom filter попробовать, чтоб избежать ограничений, которые мы в этой части видим у grin

Доводы в пользу libuv

Оно здесь: http://docs.libuv.org/en/v1.x/, https://github.com/libuv/libuv

  • Качественная и компактная вещь. На ней весь node.js и его асинхронность и много еще чего.
  • Можно зафиксировать версию и исходники встроить в build system
  • У меня с ней очень положительный опыт и не один. Вообще могу всю эту часть взять на себя и гарантировать хороший результат, и быстрый, т.к. изнутри знаю, что там
  • Будет на несколько % медленнее самописного решения на epoll, но зато mature и не один линукс
  • Туда же приделывается асинхронность и таймеры, API можно вывести приличное, на std::function, например
  • Также можно приделать, когда понадобится, http и TLS