Pull to refresh
45
0
Александр Рулёв @Rulexec

Пользователь

А с nft как раз даже владелец не может уничтожить.

А нельзя его «подарить» на какой-нибудь заведомо невалидный адрес вроде все нули?

По заголовку ожидал истории, как Reddit вёл борьбу с такими ботами и сделал honeypot с видео, которое обычные пользователи никогда бы не увидели, но боты скачали его и попали в бан.

Я себе похожую штуку делал, но с другими деталями реализации. Платка была arduino nano, вместо кнопки — педаль от швейной машинки (в ней реостат), случайный набор резисторов (подбирал так, чтобы диапазон читаемых значений побольше был). И вместо эмуляции клавиатуры (нано этого не умеет на дев-плате) — пишу в serial моменты включения/выключения (которые находятся в разных точках значений сигнала, включается при 80% нажатии, отключается при 20%, в итоге не нужно дебаунсить). Плюс небольшой скрипт на питоне, читающий этот последовательный порт и говорящий Reaper'у, какой трек нужно замьютить/размьютить (а из него уже звук после всех эффектов отдаётся системе).


Довольно удобно получилось, плюс в теории педаль можно и для чего-нибудь другого приспособить, написав другой скрипт.

Я был бы рад, если бы сервисы принимали не пароль, а хеш пароля который солится логином.


Ещё лучше — если после регистрации для того чтобы залогиниться нужно было сначала спросить у сервиса соль для логина и отправлять ему hash(hash(login+password)+salt). Тогда сервер может убедиться, что пользователь знает пароль, но если этот хеш логина будет перехвачен злоумышленником — ничего полезного он не получит, т.к. при следующем логине сервис выдаст уже другую соль для авторизации и перехваченный хеш не поможет.


Это помогало бы от того, что сервисы в итоге ломают и пароли утекают, т.к. либо слабо хешируются, либо хранятся в чистом виде, либо перехватываются, либо где-то в логах мелькают. А те, кто использует менеджеры паролей, скорее всего в меньшинстве и либо используют один пароль на всё, либо имеют какой-то паттерн.

Зачем делать целую ОС, если не хватает каких-то интеграций? Шансы того, что она станет популярной и что кто-то будет под неё что-либо делать крайне малы. Если нравится сам процесс разработки — то нет вопросов, почему бы и нет.


Мне кажется, куда более реалистично придумать что-то вроде модуля ядра/сервиса для существующих ОС, в котором будут все нужные API, чтобы можно было интегрировать что угодно с чем угодно (и пересылать, например, сообщения из одного приложения в другое, реализовав абстрактное апи Сообщений).


… а затем каким-то образом убедить всех разработчиков приложений, что им это нужно. Но чтобы навязать стандарт, нужно колоссальное количество ресурсов и времени, куда большее, чем на разработку, но однозначно меньше, чем делать целиком новую ОС.

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


Видел до 300к строк в таблице. Хотя очевидно, что пользователь в любом случае будет фильтровать, нежели искать по алфавиту (но если забрать у них такую возможность и не предложить ничего другого адекватного, будет кипиш).

TCL интересный язык. В лиспе всё это списки, в TCL — всё это строки (даже числа).


Весь синтаксис — выполнение процедуры (где первой строкой её имя, остальными — аргументы), двойные кавычки, формирующие строку с пробелами и позволяющие делать ${подстановку_переменных} и [подстановку вызова процедуры], фигурные кавычки, которые возвращают строку как есть.


В итоге, когда мы видим if {$x == 5} { ... } else { ... } это на самом деле вызов встроенной процедуры if, где первый аргумент подаётся в процедуру expr, которая умеет брать строки и проверять её на логические условия. А блоки кода — это строки, одна из которых будет за'eval'ена, если условие выполнится.

Посмотрите на Military Grid Reference System.


Это способ записи UTM-координат, который так же делит Землю на прямоугольники:


Заголовок спойлера

image


В итоге координаты выглядят как 4QFJ12345678, где 4QFJ представляет собой квадрат 100км², а цифры — это метры по x/y в данном квадрате.

Вместо разделения данных по кускам лучше использовать фонтанные коды ( https://en.wikipedia.org/wiki/Fountain_code ). Тогда можно будет шифровать рандом и результат применения кодирования, плюс шансы, что пропадут все куски с одинаковым идентификатором уменьшатся.

Лично я не сторонник слабой типизации, но мой коллега, недавно попробовавший JavaScript, почему-то был в восторге от нее. Возможно, это дело вкуса. А как считаете вы, что лучше слабая или сильная типизация?

С технологической точки зрения «лучше» конечно же формально верифицированная зависимыми типами программа с понятной человеку спецификацией. Но в реальном мире на получение доказательства корректности «правильного квиксорта» у меня уйдёт пара дней.


Каждая из статической/динамической сильной/слабой типизаций даёт свои профиты и даёт языкам свои ниши.


Люди часто наезжают на JavaScript и понятно, за что, он не идеален. Мне нравится статическая типизация. Во-первых чтобы что-то написать, нужно продумать типы, что даёт половину решения и «места, куда писать код». Во-вторых при достаточно хороших типизациях написанный код «просто работает», иногда даже с первого раза. Но чем больше разбираешься с системами типов, тем больше хочется описать, что не всегда возможно. В итоге ушёл в JavaScript, который никогда не мешает и не требуется ничего доказывать компилятору.


Типы в головах

image

о компиляции приложения для его запуска на мобилке вообще речи не велось, так как Python запускается из исходников — внес правки в код, нажал "Run" — видишь результат

Как запуск из исходников связан с восстановлением состояния интерфейса?

Для этого нужна функция, которая бы принимала строку логина плюс доказательство того, что эта строка не пуста. С видом около того:


fun login(name : String, nameIsNotEmpty : Less<0, length(name)>)

Про то, как может выглядеть Less<a, b> выше приводил пример.


В итоге чтобы в коде вызвать функцию login, нам нужно туда второй параметр передать с экземпляром Less, который будет гарантировать, что name не пусто. Если попробовать передать что-то не то — не скомпилируется, ибо типы не совпадут.


Что будет требовать обязательной проверки данных, приходящих от пользователя (например, вызовом того же isLesser(0, length(name)) из примера комментария выше).

Не нужно заставлять делать рантайм-проверки, если не используются доступы к константным индексам (иначе да, проверка обязательна). Во всех остальных случаях язык должен предоставлять возможности доказать, что все его обращения зависят от длины массива и всегда меньше её.


Чтобы если написать что-то вроде:


for (int i = 0; i <= arrayLength; i++) sum += array[i];


Компилятор сказал: звучит неубедительно, i точно всегда будет меньше arrayLength? Докажи. Чего доказать нельзя, опечатка/баг пойман.


static if в шаблонах это интересно. Но недостаточно, нужно иметь возможность использовать типы с произвольными значениями, не обязательно известными на этапе компиляции.


Если статические вычисления могут изменять структуру шаблона/типы полей и выполняются на этапе компиляции, то язык определённо не может сделать такой тип:


int x = read();

Equal<x, x> eq = Equal.refl(x);

И определять типы функций около таких:


int get(uint n, int[n] array, uint index, Less<index, n> less)

Потому что понятия не имеет, какие значения приходят в шаблон и не может произвести над ними статических вычислений.


Для возможности что-либо доказывать, нужны типы, которые могут принимать аргументами любые типы/значения, включая неизвестные на этапе компиляции.


Например:


type Less<a:uint, b:uint>
    zeroLessThanOne : Less<0, 1>
    incrementBoth : Less<a, b> → Less<a + 1, b + 1>
    incrementRight : Less<a, b> → Less<a, b + 1>

У нас есть тип «число a меньше числа b». У него есть «конструктор» — «ноль меньше единицы». И две функции для получения всех остальных значений. Больше способов получить экземпляр Less нет. Очевидно, что для всех экземпляров этого типа выполняется a < b.


uint не переполняется

Для примера будем считать, что uint у нас бесконечно большой и никогда не переполняется, иначе придётся ещё передавать доказательства того, что правая сторона не равна максимальному значению uint.


Затем мы можем написать функцию:


isLesser : a:uint → b:uint → Maybe<Less<a, b>>

Которая бы взяла Less<0, 1>, сделала Less<a, 1 + a>, если 1 + a меньше b — добила бы до Less<a, b>, иначе вернула nothing.


Затем мы можем где-то один раз получить значение Less<x, 5>, передавать его во все функции, куда передаём x и безопасно использовать x в качестве индекса по любым массивам длины больше либо равной пяти.


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


Алгебраические типы-алиасы, способные помечать значения, чтобы нельзя было умножить скорость автомобиля на год его выпуска — это круто, но зависимые типы позволяют запрещать на порядок больше.

Нужен shadow dom, которому разработчики веб-приложений могли бы указать что-то вроде «лимит памяти 10мб», чтобы пользовательский контент со стилями не мог съесть вообще всю оперативную память и уронить вкладку целиком.


А вычисления js/css в основном потоке хорошо бы ограничить в скорости исполнения на уровне браузера (например, 10мс вычисляем, 20мс спим), если превышен лимит в ~100мс времени. Во-первых если оно не уложилось, то в любом случае это надолго. Во-вторых отличная мотивация разработчиков к написанию отзывчивых интерфейсов.

Потому что когда-нибудь получится:


div.innerHTML = '<span>' + item.getDescription() + '</span>';

А в description однозначно проникнет:


<script src='//example.org/evil.js'></script>

Где-то по хабру ходили слухи, что у innerHTML производительность лучше

Тоже видел, не могу найти. Если этот HTML показывает не просто статику, а является куском интерфейса, в любом случае придётся селекторами выбирать из него элементы, чтобы навешивать обработчики/управлять отображением. И тогда cloneNode(true) должен быть быстрее, ибо не нужно парсить строку. По крайней мере в 2009 был.

Зачем нужны обязательные идентификаторы, которые будут присвоены элементам? Если для стилей, то лучше сделать их опциональными. Хорошо, что есть возможность задавать классы. Идентификаторы никогда не стоит использовать. Если очень нужно — генерировать уникальные.


В конструкторе вы используете оператор in для проверки наличия опций и записываете их в this. А дальше проверяете эти опции на !== null. Что-то мне кажется, что если не подать classListBg, случится исключение в setClasses. in не нужен, вместо x !== null для таких проверок лучше просто проверять x, либо typeof x === 'string', либо Array.isArray(x), в зависимости от того, что ожидаем. Ещё лучше — хранить в опциях дефолтные валидные значения, использование которых ничего не изменит (вроде пустого списка/нуля/etc), чтобы проверки вообще не были нужны.


Ваш delegateClick создаёт утечку памяти. Вы подписываетесь на клики по всему окну, но никогда не отписываетесь. Каждый раз, когда я буду создавать экземпляр XMC, я буду подписываться на клики и держать указатель на mf/this, который будет держать всё остальное.


Хотя и никаких методов для того, чтобы удалить все созданные элементы из DOM тоже нет.


this.body.innerHTML = this.content;

Никогда не используйте innerHTML. Кроме случаев, когда HTML небольшой, находится прямо перед глазами и в него ничего не вклеивается. Передавайте всё элементами/фрагментами. Если нужно показать текст — document.createTextNode('text'), если нужна более сложная структура — как-нибудь постройте дерево элементов, выберите узлы и используйте textContent.


А если я хочу анимацию появления окна? А если у меня в проекте уже есть модуль, отвечающий за оверлеинг интерфейса (то, что у вас делает backgroundLayer)?


Для библиотеки слишком много лишних вещей, которые могут быть мало кому нужны и нет возможностей кастомизировать поведение.


Помню тоже как-то на хабр про свой велосипедный PHP-шаблонизатор писал. Не расстраивайтесь, продолжайте абстрагировать.

Опции babel'а в js-файле. Какие проблемы перед тем как экспортировать объект с опциями пройтись по массиву плагинов и в каждый объект добавить поле?

Вы просто для всех репозиториев отдельно запрашиваете topics и только после этого их показываете. Можно было бы сразу показать репозитории и затем уже им добрасывать теги, выглядело бы быстро.


innerHTML += за гранью добра и зла. Вообще, лучше никогда не генерировать HTML руками, ибо можно легко что-нибудь непроэкранировать.


Вот тут, например:


'<p class="repository__description">' + repository.description + '</p>'

В description можно положить <script>, например.

Полифилл, да. Для IE11, к сожалению, тоже нужен полифилл, он в конструктор массив не принимает, можно забыть.


Версии фиксируются, а документацию/примеры по старым версиям потом сложно искать.


Я больше боюсь за то, что сборщик может вдруг перестать быть просто сборщиком и начнёт очень сильно влиять на сам код. Вроде влиять на import'ы.


Если мы начинаем писать код, который не может самостоятельно работать в браузере — это уже не javascript, а какой-то собственный язык. Чем мне заниматься не хотелось бы по религиозным причинам. Хотя тут на вкус и цвет.

Information

Rating
Does not participate
Location
Брест, Брестская обл., Беларусь
Date of birth
Registered
Activity