Calcule cuánto espacio se puede ahorrar después de autodestruir un contrato

Quiero hacer un breve análisis para cuantificar cuánto podría liberar uno al autodestruirse un contrato. ¿Cómo podría calcular cuánto espacio pueden ahorrar los nodos al autodestruirse un contrato determinado?

Entiendo que "no se destruye nada en la cadena de bloques", pero también entiendo que no hay necesidad de almacenar localmente el estado de un contrato si este contrato ahora se autodestruye. Nadie puede llamar a este contrato en adelante y el estado futuro no se verá afectado por este contrato después de la autodestrucción, ya que el estado del contrato no puede cambiar (aparte de ETH enviado a él) ni ser llamado. Además, hay un incentivo incorporado en el código ascendente de AUTODESTRUCT (es decir, gas negativo) que realmente no tiene sentido si los nodos no ganan nada con la destrucción de contratos. ¿Por qué crear un incentivo para algo que no tendría beneficios? Debe haber un beneficio potencial de la liberación de contratos.

¿Esto se trata a nivel de cliente? Si es así, asumo que diferentes clientes pueden tratar los contratos autodestruidos de manera diferente. En cualquier caso, ¿cómo puedo calcular esto?

Ejemplos: al observar el contrato de venta colectiva de KyberNetwork , está claro que este contrato nunca se volverá a utilizar, una situación similar en la mayoría de los contratos de venta de fichas. ¿Cuánto espacio podrían liberar los nodos al no almacenar el estado de este contrato?

Respuestas (2)

De acuerdo con esta respuesta, puede usar assembly { size := extcodesize(addr) }para saber el tamaño exacto del código en una dirección. La explicación de eso está aquí .

Entonces puede llamar eso antes de hacer una autodestrucción y emitirlo como un evento o almacenarlo en un valor en algún lugar.

¿Esto no solo devuelve los datos del código y no el tamaño del estado que ocupa este contrato? Es decir, 2 contratos podrían tener el mismo código de bytes, pero podrían tener un estado muy diferente, donde uno podría tener 1 millón de entradas y el otro 0. Me imagino que la cantidad de entradas también influye en el espacio que ocupa cada contrato en un nodo.

Inspirándome en https://ethereum.stackexchange.com/a/40280/7457 , encontré una manera relativamente fácil de hacer esto.

Después de sincronizar su nodo completo, debe consultar el estado trie en la dirección del contrato que le interesa, usando algo como

//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) { ... })

Luego debe decodificar el valor obtenido (desde rlp codificado), de modo que

var decodedVal = rlp.decode(val); 

Esto devuelve 4 valores, donde el tercer valor es el storageRoot para este contrato específico.

Al especificar la nueva raíz, creamos un flujo de lectura para repasar todos los nodos dentro de esta parte del estado trie;

// 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();

Luego, puede leer cada nodo secundario en el intento de almacenamiento del contrato, calcular cuántos bytes toman y sumar todos estos valores;

// 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;
});

Un guión completo se puede encontrar aquí .