Разница между памятью и хранилищем?

В чем разница между Memoryи Storage?

Как с точки зрения EVM, так и с точки зрения контрактного проектирования.

Спасибо!

Ответы (3)

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

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

Память временна. Хранение постоянное. Например, вы могли бы выполнять промежуточные вычисления, используя память , а затем сохранять результат в хранилище .

Детали с точки зрения EVM, их структура и стоимость газа.

Хранилище — это хранилище ключей и значений, где ключи и значения имеют размер 32 байта. Он разреженный (как хеш-таблица), и нет естественной экономии газа за счет двух 32-байтовых значений рядом друг с другом. Сохранение одного из значений в ключе 1, а другого в ключе 1000 стоит столько же газа, как и их хранение в ключах 1 и 2. (По-прежнему возможна экономия газа за счет хранения упаковки, например, установка 2 uint128значений в одном ключе. , вместо использования 2 ключей.)

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

Вики тонкостей объясняет дополнительные расходы на газ для использования памяти:

Плата за расширение памяти определяется методом вычитания интегралов. В частности, TOTALFEE(SZ) = SZ * 3 + floor(SZ**2 / 512)это общая плата за расширение памяти до SZ32-байтовых фрагментов (примечание: учитываются частично заполненные фрагменты, поэтому 33 байта = 2 фрагмента), и если конкретная операция расширяет память с размера xдо y, дополнительная стоимость газа составляетTOTALFEE(y) - TOTALFEE(x)

Затраты на хранение газа в основном составляют: 20 000 газа, если значение установлено ненулевым с нуля; 5000 газа при записи в существующее хранилище или установке значения в ноль; и возврат газа в размере 15 000 , когда ненулевое значение установлено равным нулю.

РЕДАКТИРОВАТЬ: EIP-2200, завершенный в 2018 году, содержит дополнительные пояснения по стоимости хранения, например, 800 газа для «хранения» того же значения .

Можете ли вы объяснить эту часть подробно? Сохранение одного из значений на ключе 1 и другого на ключе 1000 стоит столько же газа, как и хранение их на ключах 1 и 2.
@Rajat Я внес изменения, но не знаю, как объяснить «разреженный» дальше. Это проблема или что вы ищете?
на самом деле да. Редко я сомневаюсь, но после двух месяцев создания большего количества смарт-контрактов, чем в то время, я могу понять ваш ответ (сейчас) и оценить талант, который вы объяснили. Если возможно, можете ли вы направить меня к какой-либо документации, откуда я могу узнать о том, что происходит в фоновом режиме? (Белая книга или что-то другое) Это поможет мне лучше оценить Эфириум, и я смогу ответить, как и вы, со всеми техническими вопросами простым языком!
В целом один дешевле другого, если это не так просто, можете ли вы дать huerestic, чтобы решить, что использовать
@DanielKobe Да, память дешевле, потому что она непостоянна. Я не хотел повторять точку зрения Питера, но могу добавить уточнение.
Вы упомянули стоимость хранения, но не стоимость памяти?
@EralpB Это есть в вики-ссылке на тонкости, но я добавил ее и сейчас, чтобы ответить.
Я думаю, вы имели в виду возмещение 20 000 газа. Я думаю, что это имеет больше смысла, а также обратите внимание, что установка значения на 0 стоит 5000, что означает возмещение в размере 15000, о котором вы упоминали.
@NicSzer Цифры могут выглядеть так, как будто они складываются, но я думаю, что это скорее совпадение, и я не слежу за вашим комментарием. Цифры взяты из желтой газеты.
Почему "ПОЛ", а не "ПОТОЛОК"?
@dionyziz Я бы предположил, что это пол, потому что это типичное целочисленное деление в большинстве языков.
@eth Поскольку в нем прямо упоминается, что «подсчитываются частично заполненные фрагменты», кажется, что это будет подсчитываться с использованием здесь «CEIL» вместо «FLOOR». Частично заполненный фрагмент даст нецелое число после деления, и «CEIL» приведет к тому, что частично заполненный фрагмент будет считаться полностью заполненным фрагментом, что, я думаю, и делает расчет комиссии. Будет ли это правильным толкованием?
@eth К сожалению, я не следую формуле. Если я поставлю только uint128[1] memory t; t[0] = 10;свою функцию, стоимость вызова газа составит 21581. Когда я уберу эти 2 строки из функции (которые будут полностью пустыми), теперь это будет 21394. Разница примерно в 187 единиц газа. Я просто использовал максимум 1-2 слота. Подставляя 2 в формулу, мы получаем 6. Есть идеи?
@NikaKurashvili Часть, которую я написал о памяти, может быть очень устаревшей. Я предлагаю вам опубликовать новый конкретный вопрос, например, ethereum.stackexchange.com/questions/91197/… (или ethereum.stackexchange.com/questions/90318/… ), и кто-то может помочь. Тогда не стесняйтесь опубликовать свой собственный ответ здесь или отредактировать, чтобы обновить этот ответ. (Я уже отредактировал этот ответ на EIP-2200, так как ранее использовал более старый EIP, и его трудно отследить.)

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

Это ничего не добавляет к существующим, более подробным ответам.