Timelock, вписанный в биткоин
В блокчейне биткоина лежит работающий расшифровщик tlock. Любая инскрипция может подгрузить его рекурсией и открыть timelock-капсулу — не выходя из цепочки, без сервера и без нас. Это общее достояние: берите и пользуйтесь.
| Что | Инскрипция |
|---|---|
| библиотека tlock 23 170 байт · text/javascript |
90a1ee3d81630ca3036dd31e15d3318730a6800b0fc57af6af9b3bf1eb5294aci0
№127327908 · блок 965924 |
| реестр подписей раунды drand, дописываются потомками |
cc254c0bc57c472f6fff81119a9001844fdc3684f267dff1b0bf3d4c5921f1eai0
№127328042 · блок 965930 |
Почему это не само собой разумеется
Инскрипции рисуются в песочнице, где наружу в сеть ходить нельзя. А timelock-капсуле нужны две вещи, которых в её собственных байтах нет: код, который расшифровывает, и подпись drand, служащая ключом. Изнутри до них не дотянуться — если только они уже не лежат в цепочке. Мы их туда положили.
Как пользоваться
<script src="/content/90a1ee3d81630ca3036dd31e15d3318730a6800b0fc57af6af9b3bf1eb5294aci0"></script>
<script>
const T = window.ORACULUM_TLOCK;
// На какой раунд запечатана капсула — спросить можно без всякого ключа.
const { round, chain } = T.sealedRound(capsuleBytes);
// Расшифровать подписью этого раунда (48 байт сжатой точки G1).
const plaintext = T.unseal(capsuleBytes, signatureBytes);
</script>
Наружу торчит намеренно мало: unseal, sealedRound,
dearmor, sha256, unb64. Всё висит на
window.ORACULUM_TLOCK, больше в общую область видимости не
протекает ничего.
Откуда берётся подпись
Двумя способами, и второй переживёт всё остальное:
- Из цепочки. Обойти
/r/children/<реестр>/<страница>и прочитать потомков:{"p":"oraculum","chain":"…","s":[{"r":раунд,"g":"подпись"}]}. Мы дописываем туда после каждого своего раскрытия. - От человека. Подписи drand публичны. Покажите поле и дайте вставить ответ любого узла целиком — библиотека сама найдёт подпись в том, что вставили.
Что умеет и чего не умеет
Только расшифровку. Запечатывания, hash-to-curve и проверки подписи здесь нет намеренно: для открытия капсулы они не нужны, а каждый килобайт в инскрипции оплачивается один раз и навсегда. Поэтому 23 КБ, а не 130.
Неверная подпись не может тихо выдать чужой текст: она спотыкается сначала о проверку шифротекста в схеме IBE, потом о код подлинности заголовка age, потом о Poly1305 каждого куска.
Читается стандартный контейнер age v1 со станцей tlock,
поэтому открываются файлы официальной программы tle,
age с плагином tlock и всего прочего, что говорит на этом
формате.
Чем проверено
Это порт нашей реализации на питоне, и обе сверены с одними и теми же эталонами:
- официальные векторы RFC 9380 для hash-to-curve;
- вектор спаривания kilic/bls12-381 — библиотеки, на которой работает сам drand. Совпасть с её соглашением важнее, чем просто быть правильным: разные корректные реализации спаривания дают разные значения;
- файл, зашифрованный официальной программой
tle, — открывается байт в байт; - капсула на 200 000 байт, чтобы проверить разбиение по 64 КиБ.
Одно спаривание занимает в браузере около 25 мс.
Чего мы не утверждаем: что это проходило аудит. Не проходило. Сверено с официальными векторами и с эталонной реализацией — это сильный довод, но не доказательство. Если ставка высока, читайте код: он в цепочке, в том и смысл.
Оговорка, которую не убрать никому
Подписи drand до её раунда не существует. Биткоин не умеет забирать её сам, а отложенных транзакций с содержимым, неизвестным на момент подписания, в нём нет. Значит кто-то должен записать её в цепочку задним числом. Мы делаем это для своих капсул, вы сможете для своих. Эта последняя транзакция — не изъян замысла, а форма самой задачи.