Я хочу провести краткий анализ, чтобы количественно определить, сколько можно освободить при самоуничтожении контракта. Как я могу рассчитать, сколько места могут сэкономить узлы при самоуничтожении данного контракта?
Я понимаю, что «ничего в блокчейне не уничтожается», но я также понимаю, что нет необходимости локально хранить состояние контракта, если этот контракт сейчас самоуничтожается. Никто не может вызвать этот контракт, и после самоуничтожения этот контракт навсегда не повлияет на будущее состояние, поскольку состояние контракта не может ни измениться (кроме отправленного в него ETH), ни быть вызванным. Кроме того, в upcode SELFDESTRUCT встроен стимул (то есть отрицательный газ), который на самом деле не имеет смысла, если узлы ничего не получают от уничтожения контрактов. Зачем создавать стимул для чего-то, что не имело бы никаких преимуществ? Должна быть потенциальная выгода от освобождения контрактов.
Это решается на уровне клиента? Если это так, я предполагаю, что разные клиенты могут по-разному относиться к саморазрушающимся контрактам. В любом случае, как я могу это вычислить?
Примеры: Глядя на контракт краудсейла KyberNetwork , становится ясно, что этот контракт больше никогда не будет использоваться, аналогичная ситуация с большинством контрактов на продажу токенов. Сколько места могут освободить узлы, не сохраняя состояние этого контракта?
Вдохновленный https://ethereum.stackexchange.com/a/40280/7457 , я нашел относительно простой способ сделать это.
После полной синхронизации вашего узла вам необходимо запросить состояние trie по интересующему вас адресу контракта, используя что-то вроде
//Create database, where dbPath is the path to your data
var db = levelup(leveldown(dbPath));
// Can be obtained with web3.eth.getBlock(<blockNumber>).stateRoot
var ROOT = '0x5e27b33d4fa2349b744f7c80c60f5bcdfa9c0754b7f2be61972b220bf2ec4d78'; // 2092500
//Create trie object
var trie = new Trie(db, ROOT);
// ...
//Query the contract at
trie.get('0x' + addressHash, function (err, val) { ... })
Затем вам нужно декодировать полученное значение (поскольку rlp закодировано), чтобы
var decodedVal = rlp.decode(val);
Это возвращает 4 значения, где 3-е значение — это storageRoot для этого конкретного контракта.
Указав новый корень, мы создаем readStream для просмотра всех узлов в этой части дерева состояний;
// 3rd element in the array is storage root, 1st - nonce, 2nd - balance, var storageRoot = decodedVal[2];
//Set trie root to storageRoot
trie.root = storageRoot;
//Create stream for nodes in trie
var stream = trie.createReadStream();
Затем вы можете просто прочитать каждый дочерний узел в хранилище контракта, вычислить, сколько байтов они занимают, и суммировать все эти значения;
// Will count the byte size of the contract's storage
var contractStorageSize = 0;
stream.on('data', function (data) {
// Obtain Buffer value for current storage node
var decodedValNode = rlp.decode(data.value);
// Update contract Storage size
contractStorageSize += decodedValNode.byteLength;
});
Полный скрипт можно найти здесь .
ФАБС