Tengo un requisito siguiente que debe atenderse en dapp.
Nota:
Tratar de usar 3 for loop no parece ser una forma muy inteligente para esto, ya que se convierte en una operación costosa. Desafortunadamente, esta es la única solución que se me ocurre para satisfacer la condición anterior. ¿Alguien tiene experiencia en lidiar con esto?
// probably only one of mapping or list is needed
address[] public addressList;
mapping (address => bool) public userAddr;
function insertAddress(address[] addressUser) public returns (bool) {
// loop addressUser and check if it is unique
// loop addressUser and check if it exists in mapping
// loop and push addressUser to addressList + insert addressUser to userAddr
return true;
}
Al ver su requerimiento, haría:
address[] public addressList;
mapping (address => bool) public userAddr;
function insertAddress(address[] addressUser) public returns (bool) {
// used to check adressUser uniqueness
mapping (address => bool) memory uniq;
for(uint i = 0; i < addressUser.length, i++) {
address addr = addressUser[i];
// check if addressUser is unique
require(uniq[addr] == false);
uniq[addr] = true;
// if addr is not already list
if (userAddr[addr] == false) {
userAddr[addr] = true;
addressList.push(addr);
}
}
return true;
}
Editar:
Después de ver otro contrato, puede usar el método aquí y solicitar que todas las direcciones se envíen en orden creciente. Probablemente sea menos costoso en términos de gas ya que menos asignación de memoria.
Eso haría:
function insertAddress(address[] addressUser) public returns (bool) {
// used to check adressUser uniqueness
address lastAddr = address(0);
for(uint i = 0; i < addressUser.length, i++) {
address addr = addressUser[i];
// check if addressUser is unique
// by forcing all address to be sent
// in increasing order
require(addr > lastAddr);
lastAddr = addr;
// if addr is not already in list
if (userAddr[addr] == false) {
userAddr[addr] = true;
addressList.push(addr);
}
}
return true;
}
He creado contratos como este antes y he visto muchos de los problemas que está teniendo. En resumen, estas operaciones que está intentando realizar son costosas . Por lo tanto, la mejor manera de hacer esto es simplemente hacerlo de manera eficiente.
Para cumplir con los requisitos, colocaría toda la función en un ciclo que itera sobre cada dirección que se pasa. Para que sea lo más eficiente posible, puede usar una if
declaración para verificar si la dirección ya existe. Si es así, simplemente puede pasar a la siguiente dirección sin realizar más cálculos en la dirección actual . Dependiendo de cómo esté pasando las direcciones, esto puede suponer un gran ahorro de gasolina.
Como ejemplo, podrías hacer:
address[] public addressList;
mapping (address => bool) public userAddr;
function insertAddress(address[] addressUser) public returns (bool)
{
for (uint256 i = 0; i < addressUser.length; i++) {
if (address does not exist) {
push addressUser to addressList
insert addressUser to userAddr
}
}
return true;
}
La matriz debe ser única. Si una de las direcciones de la matriz ya existe, rechace y revierta toda la operación.
Si este es el caso, entonces lo anterior no se aplica y lo que tenía originalmente es la mejor manera de hacerlo.
Pensándolo lógicamente, para verificar la matriz debe verificar cada dirección. Esto requiere códigos de operación que verifiquen cada elemento, y no puede evitarlo. Después de realizar estas comprobaciones, debe escribir cada elemento en la cadena de bloques, que también requiere códigos de operación para cada uno de ellos. Todo este proceso es computacionalmente costoso y es la razón por la cual gran parte de esta lógica generalmente se sugiere fuera de la cadena.
Una cosa que puede hacer es comparar los valores hash de las matrices (una que está enviando y otra que está siendo revisada). Puede tomar el keccack256
de cada matriz para garantizar un hash único. Puede almacenar este hash en el contrato inteligente y enviar un hash para que se verifique, en lugar de la matriz completa. Al hacer esto, ahora solo está realizando una verificación, en lugar de N verificaciones (N es la cantidad de elementos en la matriz).
Aún se le pedirá que realice un bucle para agregar todos los elementos al contrato inteligente, pero ahora ha eliminado efectivamente un bucle.
Un ejemplo sería:
address[] public addressList;
mapping (address => bool) public userAddr;
mapping (bytes32 => bool) public doesHashExist;
function insertAddress(address[] addressUser) public returns (bool)
{
bytes32 newHash = keccak256(addressUser);
require(!doesHashExist[newHash]);
for (uint256 i = 0; i < addressUser.length; i++) {
push addressUser to addressList
insert addressUser to userAddr
}
}
doesHashExist[newHash] = True;
return true;
}
Verá que hay una nueva asignación que se usa para almacenar hashes que existen en el contrato. La función ahora solo realiza una única verificación (así como un hashing) para confirmar la existencia de la matriz. Finalmente, guarda el hash.
vicente
shane fontaine
vicente
shane fontaine
vicente
shane fontaine
vicente
shane fontaine
vicente
You can take the keccak256 of each array in order to ensure a unique hash.
Realmente no entendí cómo esto reducirá uno para el ciclo.keccak256(array[] addressList1) === keccak256(array[] addressList2)
solo puede verificar si dos listas de matrices son iguales (en términos de longitud, valor y orden de valor). No puede identificar si un elemento de una matriz existe en otra matriz o no entiendo bien la implementación.shane fontaine