Problema al recuperar de la matriz

Tengo la siguiente estructura simple y una matriz de esa estructura:

struct Document  {
      bytes32 ownerID;
      bytes32 documentID;
      bytes32 name;      
  }

  Document[] public documents;

Tengo un método storeDoc() que llena la matriz:

function storeDocument (bytes32 _ownerID , bytes32 _documentID, bytes32 _name)  {
      Document memory newDoc;

      newDoc.ownerID = _ownerID;
      newDoc.documentID = _documentID;
      newDoc.name = _name;

      documents.push(newDoc);         

    }

Y finalmente un captador. Podría haber múltiples entradas contra un OwenerID, por lo tanto, las matrices de memoria:

function getDocumentDetailsByID(bytes32 _ownerID) constant public returns (bytes32[], bytes32[], bytes32[]) {
      uint length = documents.length;

      if(registeredCandidates[_ownerID].clientAddress == msg.sender) {

          bytes32[] memory documentIDs = new bytes32[](length);
          bytes32[] memory names = new bytes32[](length);
          bytes32[] memory descriptions = new bytes32[](length);
          bytes32[] memory docYears = new bytes32[](length);


          for(uint i =0; i < length; i++) {

              if(documents[i].ownerID == _ownerID) {

                  Document memory currentDocument;
                  currentDocument = documents[i];

                  documentIDs[i] = currentDocument.documentID;
                  names[i] = currentDocument.name;

            }
          }


        return (documentIDs, names);  

      } else {
          return;
      }
  }

El problema al que me enfrento es que solo la primera entrada realizada por storeDocument() regresa usando getDocumentDetailsByID() correctamente.

¡Las segundas entradas realizadas por storeDocument() vienen como todos ceros cuando llamo a getDocumentDetailsByID() por segunda vez!

¿Alguien podría guiarme por favor, qué estoy haciendo mal? Gracias.

Respuestas (1)

Esto contiene un antipatrón.

Probablemente puedas sentirlo crecer en longitud y complejidad. Incluso si se encuentra el error lógico (realmente no estoy seguro de para qué son los arreglos de memoria) y se resuelve, encontrará que aún ha creado un contrato que no escalará.

El problema es que su forciclo itera sobre el conjunto. Cada iteración cuesta un poco de gasolina. El costo aumentará a medida que crezca el conjunto. Eventualmente, esto chocará con el límite de gas del bloque y las transacciones no podrán completarse en absoluto .

Puede resolver esto utilizando una estructura interna más eficiente que evite bucles ilimitados. Lo que está haciendo se parece mucho a las Estructuras asignadas con patrón de índice aquí: ¿Existen patrones de almacenamiento simples y bien resueltos para Solidity?

Ese, o la variante con eliminar, le dará un patrón de almacenamiento interno escalable (mismo costo de gas en cualquier escala) con acceso aleatorio por ID. Si no necesita enumerar las claves, hay un patrón aún más simple.

Espero eso ayude.

Muchas gracias. Muy bien explicado el error y el problema que ocasionaría.
He revisado sus artículos y algunas otras publicaciones sobre este tema. Grandes guías de diseño como lo son para los recién llegados como yo en Solidity. Sin embargo, me pregunto sobre el escenario con el que tengo que lidiar. Aquí, no puedo eliminar los documentos/hash de entidad que almaceno (bueno, ¡al menos durante mucho tiempo!), y los registros seguirán aumentando como se muestra en el caso de uso comercial. Bajo estas circunstancias, en su opinión, ¿una lista enlazada bidireccional sería una mejor propuesta? Muchas gracias por tu ayuda.
En la mayoría de los casos que he visto, tratar de replicar las funciones de la base de datos en un contrato inteligente es un rito de iniciación. La cuestión es que su contrato inteligente no reemplaza el almacenamiento de la base de datos. La tecnología resuelve diferentes problemas. Puede implementar índices en servidores o incluso en esquemas de almacenamiento en caché del lado del navegador. No hay una regla en contra de esto y es exactamente lo que sucede cuando visitas etherscan.io o un intercambio. La cadena de bloques demuestra que los resultados de DB/caché son veraces. En mi humilde opinión, la mejor política es evitar complicar el almacenamiento autorizado inmutable .
¡Bien! Estoy de acuerdo. Es mejor mantener datos y documentos (blobs) históricos y iterables regularmente en algún almacén de datos externo (ya que incluso los libros mayores basados ​​en claves hash pueden crecer enormemente después de cierto punto de tiempo). El único punto que me viene a la mente es una vez que se desconectan (mediante alguna operación CRUD como se describe en su publicación), cómo mantener su santidad e inmutabilidad. Me refiero a situaciones en las que sus transacciones hash también se eliminan de la cadena. Sin embargo, siempre que pueda mantener sus valores hash en el árbol jerárquico, se puede mantener su inmutabilidad.