Как мы можем получить эволюцию состояния переменной смарт-контракта?

У меня есть простой смарт-контракт с переменным цветом, в котором хранится строка.

Если я правильно понимаю, каждая транзакция может изменить состояние этой переменной и навсегда сохраняется в блокчейне. Допустим, tx#1 меняет его на красный, tx#1 меняет его на синий, tx#2 — на красный, tx#3 — на зеленый.

Я хочу иметь красный, синий и зеленый, а не только последнее состояние этой переменной цвета.

Как я могу этого добиться?

Спасибо

Ответы (2)

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

bytes32 x;

event LogChangedX(bytes32 X);

function doSomething(bytes32 newX) {
  x = newX;
  LogChangedX(x); 

Клиенты, например браузеры или серверы, могут просматривать журнал событий, чтобы обнаружить все изменения, произошедшие с "x". Использует прослушиватели событий web3.

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

Надеюсь, это поможет.

Помогает частично. Мне действительно нужно хранить цвета в виде строки. Я взял цвета в качестве примера. В моем случае это будут ссылки IPFS.
Справедливо. Вы, вероятно, захотите регистрировать и возвращать байты32 вместо целых чисел. Если это какая-то служба имен, то вам нужны геттеры с ключами, например, функция getValue(bytes32 key), и сеттеры с обоими, например, functions(bytes32 key, bytes32 value). Вы можете использовать хранилище контрактов для текущего состояния, и вы можете получить свою историю из событий, если нет важной детали, которую я упустил. LogUpdate (ключ bytes32, значение bytes32). Обычно я по умолчанию регистрирую все изменения состояния, поэтому будут LogNew, LogUpdated, LogDeleted и т. д.
Когда вы говорите о службе имен, вы имеете в виду какие-то хеш-таблицы, верно?
Извини. Ваш контракт, который возвращает ссылки, звучал для меня как разрешение имен. Это было просто предположение. Я отредактировал ответ, назвав его просто «x» и уточнив, как вы можете отслеживать изменения. Вы сможете воспроизвести каждое состояние x, через которое прошел клиент web3. Я начинаю задаваться вопросом, имеете ли вы в виду, что хотите получить доступ к этой истории внутри контракта. Если это так, то «Есть более газоемкий подход с интенсивным хранением…». Решаемая, но не тривиальная.

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

https://github.com/chafey/эфириум-события

И запись в блоге тоже:

http://chafey.blogspot.com/2017/03/applying-blockchain-to-healthcare-part_4.html

Вот ссылка на код, который перебирает события и получает старое состояние для смарт-контрактов:

https://github.com/chafey/ethereum-events/blob/master/app/client/patientChanges.js#L6