An open API service indexing awesome lists of open source software.

https://github.com/nnseva/solidity-research

Research Solidity base options
https://github.com/nnseva/solidity-research

address keccak persistent research solidity storage

Last synced: 3 months ago
JSON representation

Research Solidity base options

Awesome Lists containing this project

README

          

# Исследование адресного пространства постоянного хранилища смарт-контрактов

## Цели исследования

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

## Гипотеза

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

## План исследования

- Реализовать укороченный $keccak$ путем выборки битов из полного ключа. Считать шириной адреса $K$ бит (например $K$ младших бит $keccak256$)
- Реализовать вычисление укороченных адресов массивов и маппингов, подобное их вычислению в языке Solidity, для хранилища с адресом шириной $K >= 8$ бит.
- Рассмотреть _полный_ набор ключей маппингов и выработанных адресов массивов и маппингов для юзкейзов следующего вида:
- динамическими массивами и маппингами занято $2^S$ статических слотов в начале постоянной памяти
- ключ маппинга ограничен шириной $M < K$
- Найти минимальное расстояние $Lmin$ между вычисленными адресами массивов и значений маппингов
- Увеличивая $K$, наблюдать за динамикой значений $Lmin$ и его зависимостью от $K$, $S$ и $M$
- Задачи:
- найти зависимость $Lmin = Lmin(K, S, M)$
- найти $Lmin(S)$ при $K=256$ (полная ширина адреса), $M=160$ (ширина самого популярного типа ключа маппинга - адреса в сети Ethereum)

## Исходный код и запуск скриптов

Функция `investigate` реализует класс с заданными параметрами для выполнения исследования.

Конструктор `new investigate(K, S, M, shift, fill_arrays)` конструирует экземпляр предмета исследования с параметрами $K$, $S$ и $M$. Параметр `shift` задает сдвиг хеша $kessak256$ перед выборкой младших бит для укороченной функции $kessak$, а флаг `fill_arrays` задает необходимость учета наличия массивов.

Функции экземпляра `kecc`, `arrayof` и `mappingof` выполняют вычисление укороченного $keccak$, адреса массива и адреса значения маппинга соответственно.

Функция `analize` запускает вычисление полного набора адресов значений маппингов и адресов массивов. При возникновении коллизии, возвращается описание адреса и источников коллизии. Если коллизии не произошло, возвращается минимальное и максимальное расстояние между вычисленными адресами.

Запуск скрипта выполняется из командной строки hardhat, например:

```
npx hardhat console
> var r = require('./tests/short_storage_tests.js')
> (new r.investigate(32, 1, 14, 0, true)).analize()
```

## Результаты запусков с полным набором ключей

| K | S | M | Lmin | Lmax | comment
|------|------|-----|---------|---------|---------
| 16 | 0 | 5 | 53 | 7014 | no array
| 16 | 0 | 6 | 22 | 3605 | no array
| 16 | 0 | 7 | 17 | 2742 | no array
| 16 | 0 | 8 | 1 | 1263 | no array
| |
| 16 | 1 | 5 | 12 | 4722 |
| 16 | 1 | 6 | 10 | 3329 |
| 16 | 1 | 7 | 3 | 1392 |
| |
| 17 | 0 | 5 | 6 | 22684 | no array
| 17 | 0 | 6 | 6 | 9672 | no array
| 17 | 0 | 7 | | | (no array) conflict slot 0 keys 53, 115 address 92495
| |
| 17 | 1 | 5 | 6 | 8215 |
| 17 | 1 | 6 | 6 | 4088 |
| 17 | 1 | 7 | | | conflict slot 0 keys 53, 115 address 92495
| |
| 18 | 0 | 5 | 305 | 21440 | no array
| 18 | 0 | 6 | 87 | 16314 | no array
| 18 | 0 | 7 | 23 | 12110 | no array
| 18 | 0 | 8 | | | (no array) conflict slot 0 keys 201, 253 address 188295
| |
| 18 | 1 | 5 | 93 | 20083 |
| 18 | 1 | 6 | 23 | 9215 |
| 18 | 1 | 7 | 2 | 6676 |
| 18 | 1 | 8 | | | (no array) conflict slot 0 keys 201, 253 address 188295
| |
| 19 | 1 | 5 | 87 | 40326 |
| 19 | 1 | 6 | 54 | 24453 |
| 19 | 1 | 7 | 21 | 14531 |
| 19 | 1 | 8 | 5 | 5370 |
| 19 | 1 | 9 | 1 | 5013 |
| |
| 20 | 1 | 5 | 87 | 81044 |
| 20 | 1 | 6 | 87 | 33732 |
| 20 | 1 | 8 | 1 | 17379 |
| 20 | 1 | 9 | 1 | 7360 |
| 20 | 1 | 10 | | | conflict slot 0 key 369, slot 1 key 855 address 464915
| |
| 21 | 1 | 5 | 874 | 318273 |
| 21 | 1 | 6 | 46 | 83604 |
| 21 | 1 | 7 | 16 | 39383 |
| 21 | 1 | 8 | 4 | 24390 |
| 21 | 1 | 9 | | | conflict slot 0 key 416, slot 1 key 355 address 380988
| |
| 22 | 1 | 5 | 340 | 269236 |
| 22 | 1 | 6 | 143 | 169121 |
| 22 | 1 | 7 | 107 | 149791 |
| 22 | 1 | 8 | 24 | 42706 |
| 22 | 1 | 9 | 11 | 40507 |
| 22 | 1 | 10 | 1 | 22919 |
| |
| 23 | 1 | 5 | 340 | 543232 |
| 23 | 1 | 6 | 340 | 301622 |
| 23 | 1 | 7 | 340 | 216148 |
| 23 | 1 | 8 | 36 | 90511 |
| 23 | 1 | 9 | 11 | 65801 |
| 23 | 1 | 10 | | | conflict slot 1 keys 121, 985 address 7006401
| |
| 24 | 1 | 5 | 7657 | 858443 |
| 24 | 1 | 6 | 1275 | 562317 |
| 24 | 1 | 7 | 139 | 442935 |
| 24 | 1 | 8 | 97 | 259261 |
| 24 | 1 | 9 | 41 | 95686 |
| 24 | 1 | 10 | 4 | 63594 |
| 24 | 1 | 11 | | | conflicts (2)
| |
| 25 | 1 | 5 | 1328 | 2208082 |
| 25 | 1 | 6 | 1282 | 1236093 |
| 25 | 1 | 7 | 988 | 689847 |
| 25 | 1 | 8 | 17 | 443579 |
| 25 | 1 | 9 | 17 | 276051 |
| 25 | 1 | 10 | 3 | 128734 |
| 25 | 1 | 11 | | | conflict slot 0 keys 1711, 1936 address 14296080
| |
| 26 | 1 | 5 | 1282 | 6290056 |
| 26 | 1 | 6 | 988 | 3259186 |
| 26 | 1 | 7 | 17 | 1350555 |
| 26 | 1 | 8 | 17 | 879153 |
| 26 | 1 | 9 | 17 | 543959 |
| 26 | 1 | 10 | 17 | 315952 |
| 26 | 1 | 11 | | | conflict slot 0 keys 162, 1277 address 50672032
| |
| 27 | 1 | 5 | 28864 | 6651882 |
| 27 | 1 | 6 | 829 | 6331257 |
| 27 | 1 | 7 | 288 | 2699939 |
| 27 | 1 | 8 | 288 | 1646306 |
| 27 | 1 | 9 | 25 | 1022728 |
| 27 | 1 | 10 | 1 | 451067 |
| 27 | 1 | 11 | 1 | 362822 |
| |
| 28 | 1 | 5 | 30895 |18799374 |
| 28 | 1 | 6 | 288 |10089447 |
| 28 | 1 | 7 | 288 |7619914 |
| 28 | 1 | 8 | 25 |3589853 |
| 28 | 1 | 9 | 25 |2265379 |
| 28 | 1 | 10 | 22 |1043558 |
| 28 | 1 | 11 | 13 |551950 |
| 28 | 1 | 12 | 2 |344921 |
| 28 | 1 | 13 | 2 |151932 |
| 28 | 1 | 14 | | | conflicts (4)
| |
| 29 | 1 | 5 | 2825 |30549791 |
| 29 | 1 | 6 | 2825 |21479571 |
| 29 | 1 | 7 | 2825 |9593887 |
| 29 | 1 | 8 | 2825 |4883360 |
| 29 | 1 | 9 | 293 |3429167 |
| 29 | 1 | 10 | 21 |2081235 |
| 29 | 1 | 11 | 21 |949105 |
| 29 | 1 | 12 | 10 |511418 |
| 29 | 1 | 13 | 5 |299691 |
| 29 | 1 | 14 | 1 |168887 |
| 29 | 1 | 15 | 1 |81807 |
| 29 | 1 | 16 | | | conflicts(6)
| |
| 30 | 1 | 5 | 291866 |119208457|
| 30 | 1 | 6 | 36688 |43019933 |
| 30 | 1 | 7 | 14537 |24161115 |
| 30 | 1 | 8 | 955 |12755159 |
| 30 | 1 | 9 | 955 |7753407 |
| 30 | 1 | 10 | 385 |3596514 |
| 30 | 1 | 11 | 14 |2125253 |
| 30 | 1 | 12 | 14 |1202658 |
| 30 | 1 | 13 | 1 |671408 |
| 30 | 1 | 14 | 1 |397271 |
| 30 | 1 | 15 | | | conflict slot 0 key 25710, slot 1 key 11615
| |
| 31 | 1 | 5 | 400894 |137721932|
| 31 | 1 | 6 | 14537 |76373819 |
| 31 | 1 | 7 | 14537 |39619943 |
| 31 | 1 | 8 | 1167 |34093185 |
| 31 | 1 | 9 | 396 |13237732 |
| 31 | 1 | 10 | 14 |9843097 |
| 31 | 1 | 11 | 14 |4139320 |
| 31 | 1 | 12 | 14 |2830253 |
| 31 | 1 | 13 | 7 |1116766 |
| 31 | 1 | 14 | 2 |622015 |
| 31 | 1 | 15 | | | conflict slot 0 key 21008, slot 1 key 23559
| |
| 32 | 1 | 15 | | | conflict slot 0 key 19503, slot 1 key 10900
| |
| 33 | 1 | 15 | 1 |1469825 |
| 33 | 1 | 16 | | | conflict slot 0 keys 3372, 55032
| |
| 34 | 1 | 15 | 1 |2786410 |
| 34 | 1 | 16 | 1 |1639402 |
| 34 | 1 | 17 | | | conflict slot 1 keys 80729, 94155
| |
| 35 | 1 | 16 | 1 |3120048 |
| 35 | 1 | 17 | 1 |1606633 |
| 35 | 1 | 18 | 1 |1606633 | conflicts (3)
| |
| 36 | 1 | 17 | 1 |2941762 |
| 36 | 1 | 18 | 1 |2941762 | conflict slot 0 keys 151191, 209614
| |
| 37 | 1 | 17 | 2 |7594374 |
| 37 | 1 | 18 | 1 |5067457 |
| 37 | 1 | 19 | | | conflicts (2)
| |
| 38 | 1 | 18 | 1 |6751736 |
| 38 | 1 | 19 | | | conflicts (2)
| |
| 39 | 1 | 19 | | | conflicts slot 0 keys 106903, 145562
| |

## Выводы

### Зависимость $Lmin(K, S, M)$

Общая картина показывает монотонно убывающую в зависимости от роста $M$ функцию. При достижении $(S+M)*2 = K$ (или чуть раньше) стабильно возникает конфликт адресов.

### Значение $Lmin(K=256, M=160)$

Судя по результатам исследования, при $M=160$ конфликт ключей при _полном_ переборе всего множества $2^M$ ключей маппингов **обязательно произойдет**, поскольку даже при $S=0$, $(S+M)*2=320 > 256=K$.

### О безопасном использовании постоянной памяти в Solidity

Из исследования следует, что

- при ширине адреса $K=256$ бит (размер адреса в хранилище контракта в EVM),
- если размер значения маппинга и размер массива не превышают $L$,
- если статическая область памяти контракта занимает $2^S$ слотов,
- если динамические массивы и маппинги расположены только в статической области контракта,
- если битовый размер ключа маппинга составляет не более $M$,

то формула $(S+M) < 128 - Log_2(L)$ скорее всего, демонстрирует _безопасный способ использования смеси динамических массивов и маппингов_, который никогда не приведет к пересечению занятых областей постоянной памяти контракта при любых исходных данных контракта.

Например, считая, что для контракта объявлено $1024=2^{10}$ статических переменных контракта, являющихся маппингами и динамическими массивами, можно утверждать, что при размерах массивов и элементов маппингов не более $1024=2^{10}$, будет безопасно использовать ключи маппингов не более чем $M=107=128-10-10-1$ бит.