¿Cómo pasar argumentos a la función de estructura personalizada en la implementación?

He definido un contrato que me gustaría usar para almacenar los detalles del usuario, es decir, un campo para almacenar el hash de su documento y un campo para almacenar la dirección de un bloque que tiene otra información del usuario. Utilicé la siguiente estructura para lo mismo:

pragma solidity ^0.4.17;

contract UserDetails {
  struct User {
    string fileHash;
    address addr;
  }
  User[] userArr;

  function addUserDetail(string hash,address blockAddress) public returns (bool) {

    User memory usr;
    usr = User({fileHash:hash, addr:blockAddress});

    userArr.push(usr);

  }
}

1) ¿Es esta la estructura de datos correcta para este propósito?

2) ¿Cómo pasar los argumentos a la función addUserDetail al implementar el contrato usando web3?

Respuestas (1)

Lo modificaría un poco.

Lo primero que salta a la vista es que tiene la dirección de usuario dentro de la estructura. Eso será redundante porque querrá realizar un seguimiento de las claves de alguna otra manera. Querrá buscar por clave, por ejemplo. En eso, ya sabrás la clave que quieres buscar, ¿verdad? No es necesario almacenarlo nuevamente dentro de cada estructura.

Me di cuenta de que está almacenando hashes, así que asumo que habrá algo de almacenamiento de metadatos fuera de la cadena. Aun así, es posible que (generalmente) tenga algunos campos adicionales en la cadena. ¿Cómo saber la diferencia? Si el contrato necesita acceso a un campo para realizar alguna lógica dentro del contrato, entonces el campo pertenece a la estructura.

Hice pública la lista de claves para que un cliente pueda enumerar las claves y agregué una función para obtener un conteo rápido, porque generar un error es una forma desagradable de descubrir la longitud de la lista, en mi opinión .

pragma solidity ^0.4.17;

contract UserDetails {

  struct UserStruct {
    string fileHash;
    uint userListPointer;
    // you may continue with other non-key fields that are needed for contract logic
  }

  // unique identifiers
  address[] public userList;
  mapping(address=>UserStruct) public userStructs;

  function isUser(address userAddress) public view returns(bool isIndeed) {
      if(userList.length ==0) return false;
      return userList[userStructs[userAddress].userListPointer] == userAddress;
  }

  function addUserDetail(string hash,address userAddress) public returns (bool) {
    require(!isUser(userAddress));
    UserStruct memory usr;
    usr.fileHash = hash;
    usr.userListPointer = userList.push(userAddress) - 1;
    userStructs[userAddress] = usr;
  }

  function getUserCount() public view returns(uint count) {
      return userList.length;
  }
}

Puede encontrar algunos patrones relacionados aquí: ¿ Existen patrones de almacenamiento simples y bien resueltos para Solidity?

Y una explicación completa que casualmente usa Usuarios para el ejemplo aquí: https://medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a

Espero eso ayude.

Gracias por la explicación detallada. Como soy nuevo en blockchain y contratos, en este momento no puedo decidir cuál sería la mejor arquitectura para mi proyecto. ¿Puede compartir su correo electrónico para que pueda pedirle la orientación del proyecto? Te compartiré más detalles.
¿Y debería tener que implementar el contrato solo uno y luego llamar a la función addUserDetail en la próxima llamada api? En caso afirmativo, ¿cómo se haría a través de web3.js?
Si voy con esa arquitectura, si mi base de usuarios crece mucho, ¿seguiría siendo eficiente o deberíamos buscar cada bloque para cada usuario?
Puede crecer tan rápido como los usuarios o el administrador puedan permitirse enviar transacciones de creación al contrato. No hay límite por bloque aparte del propio Ethereum.
Gracias por responder. ¿Puede decirme por qué no debería usar un bloque diferente para cada arquitectura de usuario?
Esta frase address of a blockes difícil de entender. Si quiere decir URI of an objectalmacenado en otro lugar, entonces sí, este es un buen enfoque.
Por dirección de un bloque, me refiero a implementar un contrato para cada usuario para que pueda obtener una dirección de bloque única y con la ayuda de esa dirección de bloque (hash) podemos verificar sus datos en el futuro.