Tengo un contrato que tiene una estructura que incluye la dirección y la unidad, y el mapeo de una estructura, como esta.
struct User {
uint count;
address userAddress;
}
mapping (address => User) users;
Hay un punto en el que necesito hacer una copia de este mapeo y borrar las entradas del antiguo, como este pseudocódigo:
users_backup = users;
users = [];
Por supuesto, este código no funcionará, así que aprendí que puedes recorrerlo así:
Asignación de mapeo en Solidity
Pero eso parece caro, especialmente después de leer:
Copiar una asignación del contrato A al contrato B
Entonces, ¿cómo hago esto de manera eficiente?
Con un mapeo de 100k usuarios o 1 millón o incluso 100 millones de entradas, ¿sería factible este método de bucle? ¿O sería mejor cambiar mi arquitectura?
uint[] userCounts;
address[] userAddresses;
Podría usar una serie de matrices en lugar de mapas. Entonces, ¿podría copiar una matriz a una nueva variable y borrar la variable anterior en una o dos líneas con menos gas? Lo difícil es que incluso los arreglos tendrán que ser arreglos variables porque no puedo saber de antemano cuántos usuarios lo usarán.
¿Qué harías para minimizar el consumo de gas? No estoy seguro de cuál es el mejor patrón, ¡gracias!
No es fácil evocar un ejemplo trivial. Según los comentarios, creo que las principales preocupaciones son aproximadamente:
Es posible que tenga más caminos a considerar. Debe anticipar todas las consultas que el contrato debe realizar contra sus propios datos y encontrar una forma de acceder a la respuesta con una complejidad O (1).
Este enfoque es para darle algunas ideas:
mappings
de structs
. Por lo general, funciona mejor tener un mapeo global de todo lo que existe, con listas de punteros que satisfagan cada caso que el contrato necesita para su propia lógica de búsqueda . Por ejemplo, una lista global de todos los ID de transacción que existen y listas similares para cada usuario, en cada época. Puede utilizar address(this)
como "Usuario" para representar el conjunto global. Escribirá claves en varios lugares, pero los registros solo una vez.Puede hacer la vida mucho más fácil con estas bibliotecas de conjuntos que se ocupan de las operaciones CRUD. https://github.com/rob-Hitchens/SetTypes . En caso de que el método utilizado no esté claro, consulte esta serie: https://medium.com/robhitchens/solidity-crud-epilogue-e563e794fde
Puede hacer todo tipo de manejo de datos como bibliotecas: listas vinculadas, listas ordenadas, etc. Para algo tan complejo como suenan sus proyectos, recomiendo separar esas preocupaciones de la aplicación de línea de negocio para reducir la repetición y mejorar la legibilidad y probablemente fiabilidad.
El método de recolección de basura sugerido se basa en la noción de amortización del trabajo que se explica aquí: https://medium.com/@weka/dividend-bearing-tokens-on-ethereum-42d01c710657 . La Época actual y el correcto funcionamiento del contrato es la principal preocupación, por supuesto. Debería ser irrelevante si se limpian los datos obsoletos, pero es una buena política hacerlo, y puede hacer que los usuarios sean recompensados por eliminarlos hasta que se complete el proceso de limpieza.
Apenas:
modifier garbageCollection {
if(previousEpochStillExists) {
// get to work removing one txn/record and all references to it
}
if(nothingLeft)
// remove the epoch itsef
}
_;
}
Como idea de último momento, piense detenidamente en minimizar el almacenamiento de estado. Puede inmortalizar entradas con registros de eventos (mucho más barato). Una buena heurística es limitar el almacenamiento de estado a los valores que el contrato necesita para su propia lógica interna. Nunca para mantenimiento de registros memre porque un cliente podría estar interesado. Hay formas más eficientes de hacerlo.
Espero eso ayude.
Rob Hitchens
metapila
users_backup
. pero soy nuevo en Solidity, por lo que parecía más complejo que simplemente restablecer todas las variables en el mismo contrato...Rob Hitchens
metapila
buena vibración
There is a point at which I need to make a copy of this mapping and clear out the entries of the old one
- Ahora, ¿por qué querrías hacer algo así? Le recomiendo que revise su diseño y averigüe cómo llegó a este punto para empezar. No puedo pensar en ninguna razón en absoluto, de tener que replicar un mapeo y luego borrar el anterior.