cryptofoundry

Связаться с cryptofoundry

Расскажите, что вы хотите создать или автоматизировать.

Электронная почта
[email protected]
ADAMANT Messenger
Открыть в ADAMANT
Ecosystem & Integrations

ADAMANT IPFS Node v0.1.0: Ограниченное хранилище, GC с учетом жизненного цикла и детерминированная репликация

ADAMANT IPFS Node v0.1.0 внедряет ориентированный на эксплуатацию жизненный цикл хранения, который ограничивает рост дискового пространства, очищает неудачные загрузки, разграничивает долговечный контент и кэш, подлежащий удалению, размещает реплики детерминированным образом в наборе узлов ADAMANT, восстанавливает отсутствующие копии и сохраняет все существующие CID при обновлении.

Почему это было необходимо

Предыдущая реализация могла передавать блоки в хранилище до того, как становились известны все ограничения запросов. Прерванная или отклоненная загрузка могла оставить «мусорные» блоки, успешные загрузки оставались закрепленными без политики истечения срока действия, а явный кворум репликации или процесс восстановления отсутствовали. Это делало невозможным надежно определить, сколько дискового пространства может занять загрузка, какие файлы являются долговечными, а какие — временными, что происходит при разрыве соединения во время импорта, какие узлы отвечают за конкретный CID, может ли узел освободить место без удаления подтвержденного контента и останутся ли существующие файлы доступными после обновления кластера.

Прием данных до записи в хранилище

Загрузки отклоняются до того, как они смогут занять неограниченное дисковое пространство. Параллельные загрузки ограничены параметром storage.maxConcurrentUploads (ответ 429). Совокупный размер запроса ограничен storage.maxRequestSizeBytes (413), что применяется как к Content-Length, так и к фактически переданным байтам, поскольку чанковые запросы не объявляют свой конечный размер. Резерв диска, заданный storage.diskReserveBytes, возвращает ошибку 507, если свободного места недостаточно. Количество файлов в запросе ограничено maxFileCount (400), а размер отдельного файла — uploadLimitSizeBytes (400). Параллельные запросы резервируют место на диске атомарно, поэтому несколько загрузок не могут одновременно использовать один и тот же запас свободного пространства.

Каждый запрос владеет сеансом загрузки, который отслеживает созданные им блоки. Отказ парсера, ошибка импорта, ошибка маршрутизации, сбой строгого кворума или отключение клиента удаляют только эти новые блоки. Ранее существовавшие блоки, блоки, удерживаемые другой параллельной загрузкой, и закрепленные блоки сохраняются.

Явный жизненный цикл файла

Реестр на базе хранилища данных в /adm/files записывает жизненный цикл и учет использования диска для каждого известного CID. Состояние temporary представляет загрузку, ожидающую подтверждения или транзакционного завершения. confirmed означает долговечный контент, защищенный политикой. expired — контент, который был освобожден и может быть удален при нехватке места. Состояния pinned и heldLocally отслеживаются отдельно от логического состояния.

Переходы жизненного цикла, операции закрепления, записи в реестр, очистка загрузок, размещение реплик, восстановление и сборка мусора координируются с помощью блокировок на уровне CID и аренды коллекции для всего хранилища. Компенсация сбоев восстанавливает как закрепление, так и запись в реестре до наблюдаемого базового уровня, вместо того чтобы оставлять их в противоречивых состояниях.

Значение по умолчанию storage.confirmationRequired: false сохраняет существующий API-контракт, при котором загрузки сразу становятся долговечными. Развертывания, активирующие подтверждение, получают настраиваемое время жизни (TTL) для брошенных загрузок и должны вызывать аутентифицированную конечную точку подтверждения.

Сборка мусора с учетом давления на диск и жизненного цикла

Освобождение закрепления (pin) и удаление блоков — это намеренно разделенные решения. Освобожденный файл остается в хранилище блоков и может продолжать обслуживать запросы на чтение бесплатно. Блоки удаляются только тогда, когда хранилище превышает настроенный верхний порог или файловая система попадает в резерв диска. Это позволяет избежать удаления полезного кэша, который впоследствии пришлось бы загружать снова.

Сборщик обладает несколькими свойствами безопасности. Подтвержденный контент, хранящийся на этом узле, никогда не выбирается для удаления. Отсутствие защиты на подтвержденном файле восстанавливается до начала любого удаления. Процесс, который не может проверить долговечный контент, прерывается до выполнения первого деструктивного действия. Частичные сбои GC сохраняют записи в реестре, чтобы следующий проход мог безопасно повторить попытку. Режим «сухого прогона» (dry-run) сообщает точный план освобождения и удержания без изменения закреплений или блоков. Плановые очистки ограничены и продвигаются вперед, вместо того чтобы постоянно сканировать весь реестр.

Документированные значения по умолчанию: верхний порог 50 ГБ, нижний порог 40 ГБ, резерв свободного места 5 ГБ и плановый проход каждые 15 минут. Все значения настраиваемы. Плановая сборка мусора включена по умолчанию, но не выполняет удаление, пока место остается выше порогов безопасности. Операторы могут проверить план с помощью:

bash curl —fail-with-body
-X POST
-H “x-api-key: $ADMIN_API_KEY”
“https://ipfs.example.org/api/storage/gc?dryRun=true”

Репликация по существующей сети libp2p

Репликация работает через /adamant/replication/1.0.0, а не через дополнительную HTTP-службу. Рукопожатие libp2p подтверждает личность удаленного узла, поэтому репликации не нужен общий секрет API, второй публичный порт или отдельный демон кластера. Операции, делающие этот узел ответственным за контент, принимаются только от узлов, перечисленных в nodes. Управляющие сообщения имеют ограничение по длине. Транзакции репликации записывают узел-источник, и только этот узел может их подтвердить.

Держатели выбираются с помощью хэширования rendezvous по CID. Каждый узел с тем же списком участников независимо вычисляет один и тот же набор держателей без центрального координатора. Политика размещения по умолчанию сохраняет четыре копии для свежего контента, три копии через 180 дней и две копии через год. Количество ограничено фактическим размером сети, поэтому сеть из трех узлов, запрошенная о четырех копиях, разместит по одной копии на каждом доступном узле. Размещение сокращается в зависимости от возраста файла, а не времени последнего доступа, так как отслеживание чтений создавало бы метаданные о том, когда пользователи извлекают файлы.

Строгая долговечность загрузки является опциональной. Когда включен replication.requireQuorumOnUpload, локальный прием и удаленные реплики образуют одну транзакцию с возможностью отката: узлы подготавливают копии, источник проверяет настроенный кворум подтверждения, а затем фиксирует или прерывает каждую подготовленную реплику. Строгая конфигурация требует ackQuorum >= 2, гарантируя, что успех подтверждает наличие как минимум одной удаленной копии.

Восстановление, передача и извлечение

Задача восстановления запрашивает у узла, есть ли у него CID и есть ли место, прежде чем передавать данные. Прием ограничен параллелизмом, размером запроса, резервированием диска, таймаутом и бюджетом на узел. Узел вне текущего набора держателей передает свою долговечную копию назначенным держателям и освобождает свое закрепление только после того, как эти держатели подтвердят получение файла. Если все удаленные держатели позже исчезают, пока блоки все еще находятся локально, узел снова берет на себя ответственность, вместо того чтобы позволить последней восстанавливаемой копии исчезнуть.

Чтения также используют информацию о размещении. Перед обслуживанием CID узел подключается напрямую к узлам, которые должны его содержать, вместо того чтобы полагаться на случайный узел Bitswap. Периодическое пиринговое взаимодействие поддерживает настроенную сеть доступной после запуска. Это важно для ADAMANT Messenger: отправитель и получатель обычно используют разные инфраструктурные узлы, поэтому первое чтение получателя часто попадает на узел, который не является назначенным держателем.

Сохранение существующих файлов и CID

Обновление не выполняет повторный импорт, перезапись или переименование хранящегося контента. Генерация CID остается совместимой с предыдущим стеком, поэтому существующие ссылки на сообщения продолжают указывать на те же файлы. При запуске закрепления, созданные до реестра жизненного цикла, заполняются как подтвержденные записи. Их размеры DAG измеряются в автономном режиме, и о неполном контенте сообщается, вместо того чтобы молча регистрировать его как долговечный. API может запуститься, пока заполнение продолжается в фоновом режиме.

Важно учитывать влияние на емкость: исходное время загрузки старого закрепления восстановить невозможно, поэтому заполненные файлы изначально считаются свежими и попадают в самый широкий уровень размещения. Операторам следует планировать емкость кластера для существующего массива данных, а не только для будущих загрузок. Процессы восстановления обрабатывают этот массив ограниченными продвигающимися пакетами, а не пытаются реплицировать все за один проход.

В настоящее время предлагается только /adamant/replication/1.0.0, поэтому этот релиз предназначен для скоординированного обновления всего кластера. GET /api/storage/metrics раскрывает активную версию протокола, делая смешанное развертывание видимым.

Операционная видимость и границы доступа

Публичные маршруты «только для чтения» раскрывают состояние емкости и жизненного цикла без имен файлов, инвентаризации CID или топологии узлов: GET /api/file/:cid/status, GET /api/storage/metrics и GET /api/storage/policy. Административные изменения, такие как подтверждение, освобождение, GC по требованию, восстановление, управление закреплением и операции с топологией libp2p, требуют настроенного x-api-key.

Отчет о хранилище включает закрепленные и освобождаемые байты, доступность файловой системы, зарезервированную и используемую емкость, счетчики жизненного цикла, транзакции репликации, состояние заданий и работоспособность репликации. Он предоставляет достаточно информации для проверки обновления и мониторинга последующих проходов сбора и восстановления без раскрытия частных операционных деталей.

Значения по умолчанию, которые следует проверить операторам

Значения по умолчанию подходят для выделенного тома хранения и сохраняют текущее поведение немедленной загрузки. Совокупный размер загрузки по умолчанию составляет 512 МБ, параллельные загрузки — 32, резерв диска — 5 ГБ, TTL временных файлов — 24 часа, расписание GC — каждые 15 минут, расписание восстановления — каждые 30 минут, размещение свежих файлов — 4 копии. Кворум подтверждения загрузки по умолчанию равен 1 (репликация «как получится»), а строгий кворум загрузки отключен. Каждому оператору следует проверить емкость, пороговые значения, списки участников и уровни размещения перед развертыванием.

Верификация

Объединенная реализация прошла 232 модульных теста, 102 интеграционных теста, производственную сборку TypeScript, проверки ESLint и Prettier, аудит производственных зависимостей, а также сканирование Semgrep SAST и Semgrep OSS. Она также была протестирована в сети из четырех узлов: шестнадцать файлов были размещены на трех держателях в свежем состоянии, сошлись ровно к двум держателям после старения в следующий уровень, а затем были прочитаны побайтово идентично со всех четырех узлов в ходе 64 успешных кросс-узловых чтений. Новых зависимостей времени выполнения не введено.

Плановая последующая работа

Этот релиз устанавливает ограниченное хранилище и долговечность между узлами, но не претендует на решение всех проблем владения или членства в сети. Проблема #27 отслеживает удаление, авторизованное подписью исходного загрузчика. Проблема #28 отслеживает децентрализованное обнаружение узлов и устойчивость к атакам Сибиллы. Проблема #29 отслеживает учет трафика, задержки и ежемесячные лимиты. Шифрование контента остается обязанностью клиентского протокола ADAMANT; узел хранения управляет зашифрованным контентом по CID и не нуждается в доступе к открытому тексту.