¿Cómo almacenar una matriz de estructuras que contiene una matriz de estructuras?

Estoy tratando de crear una matriz de estructuras que contienen una matriz de estructuras.

https://gist.github.com/anonymous/65260d973a5640741a7d6174bf8fe7e6

A partir de varias búsquedas, parece que no es posible inicializar una estructura con una matriz de estructuras para insertarla en una matriz almacenada y que la mejor manera parece simplemente establecer una variable que no sea una matriz de estructura en una determinada posición en la matriz externa .

Desafortunadamente, parece que no puedo hacer que esto funcione. He intentado una variedad de cosas, pero sobre todo alrededor de lo anterior.

Si corro truffle testme sale:

Error: VM Exception while processing transaction: revert

Si intento ejecutar la función createBar en la consola, obtengo algo ligeramente diferente:

Error: VM Exception while processing transaction: invalid opcode

No estoy seguro de lo que estoy haciendo mal. Cualquier cobertizo de luz o punteros sería muy apreciado.

Respuestas (2)

Una matriz tiene una longitud, solo puede usar elementos entre 0 y la longitud de la matriz - 1.

Si desea agregar un nuevo elemento, debe aumentar el tamaño de la matriz.

function createBar(uint barNum)
  public
  returns (uint)
{
  uint barId = bars.length;
  bars.length += 1;
  bars[barId].barNum = barNum;
  return barId;
}
Vaya, esto funciona muy bien. Tiene mucho sentido, no sé por qué no pensé en hacer crecer la matriz de esta manera, supongo que pensé que había leído en alguna parte que las matrices crecen mágicamente. Me alegro de que no haya tanta magia en la solidez. ¡Gracias!
Si solo desea agregar, recomendaría usar el pushmiembro, aumentar la longitud manualmente no es una técnica de programación muy buena.

Esto es interesante.

No estoy convencido de que este tipo de anidamiento sea ideal para la mayoría de los casos porque las listas desordenadas no son útiles para el acceso aleatorio. Es posible que las estructuras asignadas con índices sean un poco más flexibles.

¿Existen patrones de almacenamiento sencillos y bien resueltos para Solidity?

Lo que estás pidiendo es factible, así que jugué con eso. Sin garantía. ;-)

pragma solidity ^0.4.18;

contract ArrayOfStructsContainsArrayOfStructs {

  struct InnerStruct {
    uint x;
  }

  struct OuterStruct {
    InnerStruct[] innerStructs;
  }

  // This can't be public because the "free" getter is too complex for the compiler to work out a default
  OuterStruct[] outerStructs;

  event LogAppendedOuterStruct(address sender, uint outerStructRow);
  event LogAppendedInnerStruct(address sender, uint outerStructRow, uint innerStructRow);
  event LogSetInnerStructValue(address sender, uint outerStructRow, uint innerStructRow, uint value);

  function appendOuterStruct() public returns(uint row) {
    LogAppendedOuterStruct(msg.sender, outerStructs.length);
    outerStructs.length++;
    return outerStructs.length-1;
  }

  // The outer structs are in an array, so specify the outerStructRow
  function appendInnerStruct(uint outerStructRow) public returns(uint row) {
    LogAppendedInnerStruct(msg.sender, outerStructRow, outerStructs[outerStructRow].innerStructs.length);
    outerStructs[outerStructRow].innerStructs.length++;
    return outerStructs[outerStructRow].innerStructs.length-1;
  }

  function setInnerStructValue(uint outerStructRow, uint innerStructRow, uint value) public returns(bool success) {
    outerStructs[outerStructRow].innerStructs[innerStructRow].x = value;
    LogSetInnerStructValue(msg.sender, outerStructRow, innerStructRow, value);
    return true;
  }

  function getInnerStructValue(uint outerStructRow, uint innerStructRow) public view returns(uint value) {
    return outerStructs[outerStructRow].innerStructs[innerStructRow].x;
  }

}

Espero eso ayude.

¡Gracias por todo esto! Probé el de Ismael a continuación y funciona. Me preocupaba un poco con esta solución que la reutilización de InnerStruct y OuterStruct provocaría que las cosas se duplicaran.
Ismael tuvo la idea correcta de agregar estructuras vacías a las matrices. Actualicé el ejemplo. Parece mejor ahora.