Considere el siguiente contrato que ilustra el problema. Aquí tenemos una matriz dinámica de asignaciones, add()
está destinada a agregar una nueva asignación nueva al final de la matriz, devolver el valor de la clave de asignación 0
y cambiar ese valor a true
. remove()
a su vez está destinado a eliminar el último mapeo de una matriz.
contract ClearMapping {
mapping(uint => bool)[] state;
// 1. add -> false
// 2. remove
// 3. add -> true
function add() returns (bool) {
uint pos = state.length++;
bool curr = state[pos][0];
state[pos][0] = true;
return curr;
}
function remove() {
state.length--;
}
}
Uno puede pensar que eliminar un elemento de mapeo de una matriz borra efectivamente ese mapeo, y que agregar un nuevo mapeo en lugar del anterior tendrá un key* -> false
elemento nuevo, todo. Resulta que no es cierto. Lo mismo sucede si intenta intercambiar elementos que tienen asignaciones dentro, todo se intercambiará excepto las asignaciones.
La única solución que veo para lidiar con esto es eliminar/reasignar manualmente todas las teclas de mapeo usadas, pero se vuelve costoso en términos de uso de gas muy rápido.
Las preguntas que busco responder son:
¡Gracias por la atención!
Para responder a su pregunta, permítame explicar cómo se ve realmente la pila EVM: en sí misma es solo un mapa de una clave a un valor, ambos de 32 bytes de longitud.
un mapa de solidez, mapas desde sha3(mapId . key) a un valor dado en la pila evm. Esa es también la razón por la que uno no puede iterar a través de todas las claves en un mapa, porque están "aleatorizadas" a través de toda la pila de evm.
una matriz de solidez se asigna desde sha3 (arrayId) + índice a un valor. Aquí podemos iterar si conocemos el arrayId simplemente incrementando el índice.
(Aquí no estoy realmente seguro de si la longitud de una matriz también se guarda).
Lo siguiente es solo una especulación, ya que estoy completamente seguro de cómo la solidez resuelve esto: si ahora tiene una matriz de mapas, lo que realmente hace es mapId = sha3 (arrayId) + index. Puede iterar a través de ellos. Sin embargo, si guarda algo en un mapa, haga lo siguiente:
sha3((sha3(arrayId) + index) . key ) = value
Pero al eliminar el último elemento del mapa, pierde la identificación de matriz para el mapa, pero debido a que uno no puede iterar a través de los mapas sin conocer las claves, su valor se conserva.
Sin embargo, los arreglos múltiples no tienen este problema:
import "dapple/test.sol";
contract A is Test {
uint[][] multiarray;
function testMultiArray() {
//@log multiarray length: `uint multiarray.length`
//@log incrementing multiarray
multiarray.length++;
//@log multiarray length: `uint multiarray.length`
//@log multiarray[0] length: `uint multiarray[0].length`
//@log incrementing multiarray[0]
multiarray[0].length++;
multiarray[0].length++;
//@log multiarray[0][0]: `uint multiarray[0][0]`
//@log set value to 1
multiarray[0][0] = 1;
multiarray[0][1] = 1;
//@log multiarray[0] length: `uint multiarray[0].length`
//@log multiarray[0][0]: `uint multiarray[0][0]`
//@log multiarray[0][1]: `uint multiarray[0][1]`
//@log decrementing multiarray
multiarray.length--;
//@log multiarray[0] length: `uint multiarray.length`
//@log incrementing multiarray
multiarray.length++;
//@log multiarray[0] length: `uint multiarray[0].length`
multiarray[0].length++;
multiarray[0].length++;
//@log multiarray[0][0]: `uint multiarray[0][0]`
//@log multiarray[0][1]: `uint multiarray[0][1]`
}
}
Producirá la siguiente salida:
test multi array
LOG: multiarray length: 0
LOG: incrementing multiarray
LOG: multiarray length: 1
LOG: multiarray[0] length: 0
LOG: incrementing multiarray[0]
LOG: multiarray[0][0]: 0
LOG: set value to 1
LOG: multiarray[0] length: 2
LOG: multiarray[0][0]: 1
LOG: multiarray[0][1]: 1
LOG: decrementing multiarray
LOG: multiarray[0] length: 0
LOG: incrementing multiarray
LOG: multiarray[0] length: 0
LOG: multiarray[0][0]: 0
LOG: multiarray[0][1]: 0
Oleksii Matiiasevych
Denis
Oleksii Matiiasevych
key => bool
uno puede usaruint[]
una colección de lotes de 256 bools cada uno. Pero ¿key => uint
y los demás?