¿Cómo devolver un tipo de mapeo?

tengo un contrato con un mapeo dentro de una estructura

contract Voting {
 struct voter {
   address voterAddress;
   uint256 tokensBought;
   mapping (bytes32 => uint256) tokensUsed;
 }
 mapping (address => voter) public voterInfo;
}

Quiero una función que devuelva la información de los votantes dada una dirección. Descubrí que no puedo hacer que una función devuelva una estructura. Entonces, traté de escribir una función que devuelve tokensBought y tokensUsed como se muestra a continuación:

function voterDetails(address user) returns (uint256, mapping (bytes32 => uint256)) {
  return (voterInfo[user].tokensBought, voterInfo[user].tokensUsed);
}

Cuando intento compilar este código, obtengo los siguientes errores:

Error: se requiere el tipo para vivir fuera del almacenamiento.

Error: el tipo interno no está permitido para funciones públicas o externas

Parece que no puedo devolver el tipo de mapeo en una función. ¿Cómo escribo una función que devuelva toda la información de los votantes?

Respuestas (1)

Necesita dividir la interfaz en partes más pequeñas. En la práctica, creo que querrá ampliar un poco el patrón de almacenamiento interno.

El mapeo iterable viene a la mente. Mantiene listas de claves para asignaciones en matrices. Algo como esto:

  struct VoterStruct {
    address voterAddress;
    uint256 tokensBought;
    mapping (bytes32 => uint256) tokensUsed;
    bytes32[] tokenIndex; // a list of mapping keys that exist for the voter
  }

  mapping (address => VoterStruct) public voterStructs;

Luego puede exponer funciones que permiten iterar sobre listas mientras el contrato devuelve un conjunto de valores a la vez. Muy esquemático para inspirar algunas ideas:

// client can discover how may tokens are in the list for one voter
function getVoterTokenCount(address voter) returns(uint tokenCount) {
    return voterStructs[voter].tokenIndex.length;}

// client can discover the tokenId for a voter in a given row
function getVoterTokenAtIndex(address voter, uint index) returns(bytes32 tokenId) {
    return voterStructs[voter].tokenIndex[index];}

// client can discover token used by voter and tokenId
function getVoterTokenUsed(address voter, bytes32 tokenId) returns(uint tokensUsed) {
    return voterStructs[voter].tokensUsed[tokenId];}

// append keys to the list as you go
function insertVoterToken(address voter, bytes32 tokenId) returns(bool success) {
    voterStructs[voter].tokenIndex.push(tokenId);
    return true;}

Espero no haber fallado en la sintaxis. Podría ser posible esbozar un poco más el contrato. Necesitaría una descripción general de lo que va a hacer. Cuando uso este patrón, siempre agrego algunas reglas para garantizar que no haya claves duplicadas, y así sucesivamente.

De todos modos, posiblemente las pistas inspiren algunas ideas.

Espero eso ayude.

Gracias, eso ayuda. Todavía tengo curiosidad, ¿por qué el tipo de retorno no puede ser un mapeo? ¿Es solo que la solidez aún no lo ha implementado o hay alguna razón por la que no se puede hacer en absoluto?
No hay forma de enumerar los elementos en un mapeo. Para saber qué devolver, Solidity necesitaría realizar un seguimiento de todas las claves que se han utilizado, lo cual no hace.
No se puede devolver una asignación porque sería de longitud variable si se pudiera enumerar, pero no se puede. Podemos rastrear las claves nosotros mismos y obtener un efecto similar.
Ahora entiendo, ¡gracias @RobHitchens y @TjadenHess!
Hay muchos casos en los que se requiere tener la lista de claves de mapeo. Hay dos formas de crear una lista de este tipo: 1 verificando todos los miembros existentes en la lista en busca de duplicados antes de agregar la entrada, 2 verificando la asignación antes de cambiar para ver si el valor en la clave es 0. Si es 0, entonces la clave "podría " ser nuevo.
@RFVenter. La respuesta anterior aborda la pregunta tal como se hizo y también muestra una forma de realizar un seguimiento de las claves en las asignaciones. ¿Es posible que "comprobar todos los miembros existentes en la lista" sea incorrecto? Sería desastroso iterar todas las claves en una lista de n filas (antipatrón). Las asignaciones, por otro lado, no proporcionan ninguna forma de enumerar las claves. Realmente no estoy seguro de lo que quisiste decir.