Блог
Байты прошли два радиоскачка между четырьмя платами и пришли байт-в-байт, а печать покрытия, пересчитанная независимо в трёх точках, сошлась во всех трёх. Что это доказывает, чего не доказывает, на чём всё это сделано и где серийные радиостанции откровенно впереди.
Четыре одноплатных радиоузла на столе, одна подсеть, 2,4 ГГц. Байты ушли с первой платы, прошли два радиопрыжка и пришли на четвёртую без единой ошибки. В трёх точках этого пути печать покрытия пересчитывалась независимо, и все три сошлись: 0x9DBE2510. Это весь результат, и дальше речь о том, чего он стоит.
Троичность здесь -- это одна конкретная схема, и назвать её стоит раньше всего остального: двухбитный код веса, где 01 выбирает +x, 10 выбирает -x, а всё прочее -- ноль. Умножение превращается в смену знака, умножитель исчезает, дальше работает обычное дерево сумматоров. На этом единственном примитиве держатся согласованный фильтр на 8 отводов, 63-отводный приёмник ПСП, систолическая плитка и небольшой классификатор, все веса которого равны -1, 0 или +1.
Это же слово в том же репозитории носит и вторая, никак не связанная вещь. У формата GF-T экспонента «уравновешенно-троичная» лишь в том смысле, что её пространство кодов содержит 3^Et значений, отцентрованных смещением. В железе пересчёт экспоненты -- это a_off + b_off + carry - BIAS, обычное двоичное сложение. Ни один трит нигде не материализуется. Троичными называются обе вещи, а троичной схемой является только первая.
| Узел | Что в нём троичного | Наивысший достигнутый статус | Чем подтверждено |
|---|---|---|---|
| Проба троичного узла | Сам примитив: процессор подаёт отсчёт и двухбитный вес, матрица отвечает +x, -x или 0 | Работал в матрице платы 19 августа 2026: якорь 0x47C0, пульс идёт, ответы +42, -42, 0, 0, +127, -127 для кодов 01, 10, 00, 11 -- бит в бит | results/ps7_probe_silicon_2026-08-19.log, получен в тот же день |
| Согласованный фильтр на 8 отводов | Отводы со знаковым выбором; код синхронизации использует все три символа, два отвода из восьми нулевые | Работал в матрице Zynq XC7Z020 на реальном записанном эфире: 256 из 256 бит в бит | results/cstream2.log, ветвь feat/own-rtl-in-radio-path |
| 63-отводный приёмник ПСП | 63 отвода со знаковым выбором в уравновешенном дереве сумматоров, ни одного блока DSP48E1 по построению | Работал в матрице: 256 из 256 бит в бит, с отрицательными контролями и двумя неисправностями, внесёнными в сам битстрим и упавшими ровно как предсказано | results/pn63_success.log, negative_controls.log, bitstream_mutants.log, та же ветвь |
| Систолическая плитка и классификатор | Тот же примитив; в файле весов классификатора ровно три кода и ничего сверх | Синтезировано: 527 таблиц, 45 цепочек переноса, 165 триггеров и ни одной ячейки DSP48E1 | yosys synth_xilinx на tern_corr8_stream, перезапущено, а не переписано |
| Арифметика GF-T в RTL | Пространство кодов экспоненты в 3^Et значений; само сложение двоичное | Промоделировано и синтезировано: 16-битное умножение -- 1 DSP48E1, 47 таблиц, 18 цепочек переноса | fpga/gft/SYNTH_RESULTS.md, воспроизведено |
| GF-T на кремнии | Тот же формат, исполняемый на Artix-7 | Не доказано. Заявлено подробно, но ни лога размещения, ни битстрима, ни захвата UART нет ни в одной ветви | docs/VERIFIABLE_COMPUTE.md утверждает; fpga/gft/SYNTH_RESULTS.md пишет, что трассировка и загружаемый битстрим не доказаны |
С последней строкой было хуже, чем просто пробел, когда страница вышла впервые: один документ сообщал, что движки прошиты в плату, другой в том же каталоге -- что загружаемый битстрим не доказан. Верным одновременно это быть не могло. Исправление написано и открыто публично: запрос на слияние tri-net 382 переводит утверждение в разряд результатов моделирования и называет четыре артефакта, которые закроют вопрос, -- файл ограничений с заполненными выводами, лог трассировки с именем верхнего модуля, полученный из него битстрим и транскрипт прошивки с чтением кода кристалла. Приведённые числа вопрос решить и не могли: это те же эталонные векторы, что лежат в стендах моделирования.
Эта строка -- не цитата из старого журнала. Она получена по ходу написания страницы, на плате, стоящей на столе: цепочка JTAG отдаёт код кристалла 0x23727093, тот самый XC7Z020, о котором говорит страница, а после загрузки матрица ответила якорем 0x47C0, который отличает наш образ от вендорского. Первая попытка перезагрузила плату -- запись битстрима, пока radio-DMA в середине транзакции, вешает процессор, и заканчивает это только сторожевой таймер, -- поэтому теперь загрузка сначала разбирает шину: снять потоки отсчётов, отвязать ядра радиотракта, отвязать оба движка DMA, опустить Ethernet из матрицы и только затем писать. Обычная перезагрузка вернула вендорский образ и радио, поэтому такую проверку и можно было себе позволить.
Это не продукт, который можно купить. Это открытый репозиторий -- один крейт на Rust под Apache-2.0 -- и журнал измерений на железе, которое любой может заказать, записанный так, чтобы посторонний мог их повторить. Что делает код: перегоняет байты между радиоузлами и на каждом прыжке выпускает подписанную квитанцию о том, какой узел сколько байт пронёс и в какую эпоху.
Железо -- четыре платы Puzhi P201Mini, на каждой Zynq-7020 и радиотракт AD9361, плюс одна ALINX AX7203 на XC7A200T для арифметики на стенде. Платы вы покупаете сами, здесь ничего не продаётся.
Проверяемое утверждение узкое, и оно бухгалтерское, а не радиотехническое: когда байт пересекает сеть независимых радиоузлов, может ли сеть выдать запись о том, кто его нёс, которую третья сторона проверит, не доверяя ни одному из них?
| Слой | Что это в действительности | Где исполняется | Артефакт |
|---|---|---|---|
| Плата узла | Puzhi P201Mini: Zynq-7020, кристалл xc7z020clg400-1, два ядра Cortex-A9 и матрица класса Artix, рядом трансивер AD9361 | Четыре штуки в одной подсети | tools/jtag-bootstrap/README.md |
| Плата стенда | ALINX AX7203: Artix-7, кристалл xc7a200tfbg484-2, 740 блоков DSP48E1 и 134 600 шестивходовых таблиц | Стол, отдельно от радиоузлов | fpga/gft/gft_alu_ax7203.xdc |
| Радиотракт | Analog Devices AD9361, управляется из ARM-Linux через интерфейс IIO -- гетеродин, полоса, частота дискретизации, уровень сигнала | В Linux узла, не в матрице | tools/ad9361_config.rs |
| Поток битстрима -- открытая часть | yosys synth_xilinx, затем nextpnr-xilinx, затем prjxray fasm2frames и xc7frames2bit в контейнере openXC7. Vivado в этом пути нет нигде | На хосте, в Docker | fpga/ternary/ps7/build/run_openxc7.sh |
| Загрузка -- всё ещё вендорская | BOOT.BIN и FSBL берутся из Xilinx bootgen через PetaLinux либо из фирменного образа платы. Поток для матрицы открыт, цепочка загрузки под ним -- нет | На хосте, при подготовке карты памяти | docs/LOCAL_FLASH.md |
| Программная часть | Один крейт на Rust, trios-mesh, редакция 2021, Apache-2.0: 10 805 строк в src/ и 432 тестовых блока. Над ним 107 спецификаций t27, порождающих Rust, C и Zig | Кросс-сборка armv7 musl, исполняется на Cortex-A9 | Cargo.toml, tri-facts.json |
| Тот канал, что реально пронёс байты | Модем DBPSK на поднесущей 768 кГц с 63-битной ПСП-преамбулой и разностным детектором, к AD9361 через iio_writedev и iio_readdev | Программно на ARM узла, без единого нашего битстрима в матрице | smoke/DEPIN_OTA_CLOSED_2026-07-18.md |
| Шифрование сеанса | ChaCha20-Poly1305, ключ из рукопожатия X25519 через HKDF-SHA256, направленный счётчик, окно защиты от повтора на 64 кадра, смена ключа каждые 2^20 кадров | ARM узла и хост | src/crypto.rs |
| Квитанции | Подписи Ed25519, проверяемые по открытому ключу исполнителя; дайджесты SHA-256 и объединение в дерево Меркла | ARM узла и хост | src/bin/trinet_a2a_node.rs |
| Печать покрытия | epoch_seal: три круга 32-битного перемешивателя со сдвигом и сложением плюс циклический сдвиг. Связывает личность, эпоху и число байт в одно 32-битное слово | На узлах во время прогонов ретрансляции | specs/tri_depin.t27 |
| Маршрутизация | Метрика ETX с оценкой доставки WMEWMA, подсеть 10.42.0.0/24, время жизни пакета 8. Помечена как -sim, проверяется на хосте. Рабочий демон использует UDP поверх Ethernet вместо радиоканала | Тесты на хосте, демон на узлах | src/routing.rs, src/bin/trios_meshd.rs |
| Арифметика в матрице | GF-T, лестница чисел с плавающей точкой и троичным порядком. Шестнадцатибитный умножитель синтезируется в 1 DSP48E1, 47 таблиц и 18 цепочек переноса | Настоящий кремний AX7203, ответы по UART | fpga/gft/SYNTH_RESULTS.md |
Две строки этой таблицы стоит прочитать дважды. Поток битстрима действительно открыт -- образ матрицы не производит ни один вендорский инструмент, -- но цепочка загрузки под ним по-прежнему вендорская, и утверждать обратное было бы самой лёгкой ложью на этой странице. И модем, который реально нёс байты, работал программно на ядре ARM: ни один наш битстрим никогда не был загружен в матрицу узла.
epoch_seal -- это три круга 32-битного перемешивателя. Он работает на ключе и связывает личность, эпоху и число байт, поэтому совпадение печати у двух свидетелей -- довод в пользу того, что они учли один и тот же трафик. Но это не криптографический хеш, ширина всего 32 бита, и в комментарии самой спецификации сказано, что для настоящих расчётов печать следовало бы ещё и подписывать. Трафик сеанса защищён отдельно, через ChaCha20-Poly1305; печать -- учётный дайджест сверху, и он слабее.
| Прогон | Результат | При каких условиях | Записано в |
|---|---|---|---|
| Два радиопрыжка, .13 -> .12 -> .10 | Печать покрытия 0x9DBE2510 одинакова во всех трёх точках; 4 различных полезных нагрузки на первом прыжке | Один общий канал 2,4 ГГц, накопить-и-передать, прыжки разнесены во времени, а не одновременны | DEPIN_2HOP_RELAY_2026-07-18.md |
| Два прыжка с упорядоченным сообщением в 31 байт | 6 из 6 кусков на обоих прыжках; печать 0x37A9A9F6 одинакова у источника, ретранслятора и приёмника | Фиксированная тестовая строка в циклическом буфере | DEPIN_MSG_RELAY_2026-07-18.md |
| Два прыжка, работающие одновременно | 5 из 5 кусков на ретрансляторе при работающем собственном передатчике; печать 0xE0AA4F5D одинакова в трёх точках | Разнос приёма и передачи 50 МГц на одном AD9361 в режиме FDD | DEPIN_FDD_PIPELINE_2026-07-18.md |
| Три прыжка, .13 -> .12 -> .11 -> .10 | Пик корреляции 1,000, 0,998, 0,998; ошибок 0 из 128 на каждом прыжке, с первой попытки на каждом | Передаёт один в один момент времени; захват повторялся до чистого | DEPIN_RELAY3_RTI_2026-07-19.md |
| Четыре узла, один передатчик, три свидетеля | Все три свидетеля независимо насчитали 8 различных кадров и одну и ту же печать 0xCDB1F3B1 | Каждый свидетель слушал эфир сам и учитывал то, что услышал | DEPIN_STREAMING_4NODE_2026-07-18.md |
| Восемь байт по воздуху, замкнутый цикл | Пик корреляции 1,000, ошибок 0 из 64, нагрузка восстановлена точно -- дважды | Кадр 8 байт, гетеродин передачи 2400 МГц при усилении -10 дБ | DEPIN_OTA_CLOSED_2026-07-18.md |
| Развёртка по мощности передачи | -10 дБ: 0 ошибок из 64. -20 дБ: 0 из 64. -30 дБ: 0 из 64. -40 дБ: 34 из 64 -- канал рвётся | Усиление -- это настройка AD9361 в дБ, а не излучаемая мощность | DEPIN_RADIO_RECEIPT_2026-07-18.md |
| Насколько разнести два канала на одном кристалле | 50 МГц и 20 МГц: чисто. 15 МГц и 13 МГц: на части кусков печать не сходится | Ограничение аналоговое; сужение цифрового фильтра приёма не помогло | DEPIN_FDD_SWEEP_LIVE_2026-07-18.md |
| Захват на 16 мегабайт, демодуляция офлайн | 815 кадров, 748 чистых (92%), 6520 байт, одна квитанция | Около 136 мс эфира; примерно 3 с обработки на ARM. Один прогон, без повторов | DEPIN_STREAMING_4NODE_2026-07-18.md |
| Зачем понадобилось отслеживание кадров | Фиксированная сетка: 0 чистых из 819. Кварцы двух плат на 30,72 МГц расходятся примерно на 10 миллионных долей | Контрольное условие, которое заменило отслеживание по захваченной позиции | DEPIN_STREAMING_4NODE_2026-07-18.md |
| Арифметика на настоящем кремнии | 5 из 5 умножений GF-T16 и 3 из 3 скалярных произведений совпали побитово с образцом на хосте | AX7203, поток openXC7, ответы по UART | docs/VERIFIABLE_COMPUTE.md |
| Враждебные случаи на защищённом канале | Отклонены 5 негативов: подмена задания, подмена результата, повтор счётчика, перестановка операндов и слепой ретранслятор | Настоящий AEAD, заголовок маршрутизации как связанные данные | docs/VERIFIABLE_COMPUTE.md |
Первая попытка первого прыжка дала не 0x9DBE2510, а 0x7ACD8A11 -- и не из четырёх различных нагрузок, а из пяти: один кадр пришёл с битовыми ошибками, прошёл порог корреляции 0,9 и раскодировался в нагрузку, которой никто не передавал. Печать сделала ровно то, ради чего она нужна: не сошлась. После этого добавили фильтр по большинству среди повторных копий и повторяли прогон, пока три точки не совпали.
Вот эту часть и стоит хранить. Схема учёта, которая никогда не расходится сама с собой, попросту не проверена; эта разошлась, расхождение довели до конкретной слабости декодера, и в журнале записаны и сбой, и починка.
Уберите радио -- останется учёт. Каждый узел ведёт нарастающий счёт пронесённых байт, связывает его со своей личностью и с эпохой и подписывает результат. Второй узел, слышавший тот же трафик, независимо получает тот же дайджест. Расчёт после этого -- арифметика по записям, которые могут сверить несколько сторон, а не заявление того, кому принадлежит базовая станция.
Поэтому самое интересное в двухпрыжковой ретрансляции -- не байты. Это три независимых пересчёта одного числа тремя машинами, которые друг с другом не сговаривались.
| Ситуация | Что доказывает квитанция | У кого есть причина платить |
|---|---|---|
| Кому-то платят за покрытие там, где его никто не проверяет: сельский ретранслятор, кампус, здание | Что трафик действительно прошёл через этот узел в эту эпоху, и это подтверждают соседи, которые его тоже слышали | Тот, кто финансирует покрытие и сегодня вынужден верить оператору на слово |
| Сеть датчиков выставляет счёт за доставленные данные | Сколько байт дошло до дальнего конца, а не сколько было отправлено в надежде | Тот, кому выставляют счёт |
| Подрядчик заявляет, что канал работал в период аварии | Поэпохные счётчики от нескольких свидетелей, которые один оператор подделать в одиночку не может | Страховщики и тот, кто писал условие об уровне обслуживания |
| Вычисление выполняется на устройстве, которое вам не принадлежит | Что возвращённый ответ соответствует подписанному обязательству по входным данным и ходу вычисления | Тот, кто платит за вычисления |
Ни одно из этого не является внедрением. Никакой расчётный контракт нигде не развёрнут, и покупателя ни на что из перечисленного сегодня нет. Это те ситуации, под которые ставились измерения.
| Кто | Что продаёт | Чего не даёт | В чём отличие здесь |
|---|---|---|---|
| Persistent Systems, MPU5 | Боевая MIMO-радиостанция; предел по паспорту до 150 Мбит/с, криптомодуль по FIPS 140-2 уровня 2 | Ни описания сигнала, ни спецификации маршрутизации, ни векторов соответствия | Здесь договор о канале -- файл в репозитории под Apache-2.0 |
| Silvus, StreamCaster | Собственный MIMO-сигнал, 100+ Мбит/с, средняя задержка 7 мс в полосе 20 МГц | Ни опубликованной спецификации, ни векторов соответствия, ни цены | Наибольшая показанная сеть здесь -- четыре узла; три из них независимо учли один и тот же эфир |
| Rajant, Kinetic Mesh | Запатентованная маршрутизация второго уровня без корневого узла, сотни Мбит/с на радио | Базовая реализация способна, но не сертифицирована | Криптография здесь -- ChaCha20-Poly1305 с X25519, описана в репозитории и не сертифицирована никем: гарантия слабее, и об этом сказано прямо |
| Doodle Labs, Mesh Rider | Экономичные многодиапазонные радиостанции для дронов; NASA измерила 37,9 / 5,6 / 1,2 / 0,3 Мбит/с на одном-четырёх прыжках | Шифрование и внутренности маршрутизации не опубликованы | Здесь байты пережили два прыжка без ошибок при совпавшей печати, но пропускная способность ни на одном числе прыжков не измерялась вовсе |
| Meshtastic | Открытая LoRa-сеть, 0,3-300 кбит/с, AES-256 программно, десятки километров | Ни широкой полосы, ни слоя учёта и вознаграждения | Широкая полоса 2,4 ГГц и слой квитанций -- против несопоставимо меньшей и куда менее зрелой экосистемы |
| openwifi / open-sdr | Полностью открытый Verilog для 802.11 с физическим уровнем OFDM прямо в матрице ПЛИС | Не сетевой по природе; целится в потребительский стандарт | Ближайший открытый конкурент, и он впереди там, где это важнее всего: его физический уровень работает в матрице. Наш работал программно на ARM |
| AREDN | Свободная прошивка, превращающая серийные маршрутизаторы в сеть 2,4/5 ГГц, 5-50 км | Ни своего сигнала, ни слоя учёта и подтверждения | Впереди по зрелости и числу развёрнутых узлов -- репозиторий сам записывает это себе в недостатки |
| Helium и похожие токен-сети | Вознаграждение операторам точек в токенах плюс разгрузка трафика операторов связи | Участие не привязано к конкретному подтверждённому устройству | Здесь три свидетеля независимо получили одну и ту же печать покрытия из эфира, который каждый слышал сам |
Эту таблицу стоит читать по проигрышам. По пропускной способности, задержке, дальности, зрелости экосистемы и сертификации серийные радиостанции впереди с разрывом, который не назовёшь близким, а openwifi впереди по единственной оси открытого железа, которая важнее прочих. Отличие здесь узкое: слой учёта, договор о канале в виде файла, а не строчки в паспорте, и журнал, где отказы записаны наравне с удачами.
Партнёр, присоединяющийся сейчас, присоединяется к дисциплине измерений, а не к сети. Что есть в наличии -- это инструмент: железо, которое любой может купить, поток сборки без вендорской лицензии на пути к матрице, и журнал, где отказы записаны с той же тщательностью, что и результаты.
Каждая цифра выше измерена, и рядом с ней названы её пределы.