Wie gebe ich einen Zuordnungstyp zurück?

Ich habe einen Vertrag mit einer Zuordnung innerhalb einer Struktur

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

Ich möchte eine Funktion, die Wählerinformationen bei einer Adresse zurückgibt. Ich habe herausgefunden, dass eine Funktion keine Struct zurückgeben kann. Also habe ich versucht, eine Funktion zu schreiben, die tokensBought und tokensUsed wie folgt zurückgibt:

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

Wenn ich versuche, diesen Code zu kompilieren, erhalte ich die folgenden Fehler:

Fehler: Typ ist erforderlich, um außerhalb des Speichers zu leben.

Fehler: Interner Typ ist für öffentliche oder externe Funktionen nicht zulässig

Sieht so aus, als ob ich den Zuordnungstyp in einer Funktion nicht zurückgeben kann. Wie schreibe ich eine Funktion, die alle Wählerinformationen zurückgibt?

Antworten (1)

Sie müssen die Schnittstelle in kleinere Stücke zerlegen. In der Praxis sollten Sie das interne Speichermuster ein wenig erweitern, denke ich.

Iterable Mapping kommt mir in den Sinn. Sie führen Listen von Schlüsseln zu Zuordnungen in Arrays. Etwas wie das:

  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;

Dann können Sie Funktionen verfügbar machen, die das Iterieren über Listen ermöglichen, während der Vertrag jeweils einen Satz von Werten zurückgibt. Sehr skizzenhaft, um einige Ideen zu inspirieren:

// 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;}

Hoffe, ich habe die Syntax nicht vermasselt. Eventuell könnte man den Vertrag noch ein wenig skizzieren. Benötige eine allgemeine Beschreibung dessen, was es tun wird. Wenn ich dieses Muster verwende, füge ich immer einige Regeln hinzu, um sicherzustellen, dass es keine doppelten Schlüssel gibt, und so weiter.

Wie auch immer, möglicherweise inspirieren die Hinweise einige Ideen.

Ich hoffe es hilft.

Danke, das hilft. Ich bin immer noch neugierig, warum kann der Rückgabetyp keine Zuordnung sein? Ist es nur so, dass Solidity es noch nicht implementiert hat, oder gibt es einen Grund, warum es überhaupt nicht möglich ist?
Es gibt keine Möglichkeit, die Elemente in einer Zuordnung aufzuzählen. Um zu wissen, was zurückgegeben werden soll, müsste Solidity alle verwendeten Schlüssel verfolgen, was es nicht tut
Eine Zuordnung kann nicht zurückgegeben werden, da sie eine variable Länge hätte, wenn sie überhaupt aufgezählt werden könnte, aber das ist nicht möglich. Wir können die Schlüssel selbst verfolgen und einen ähnlichen Effekt erzielen.
Jetzt verstehe ich, danke @RobHitchens und @TjadenHess!
Es gibt viele Fälle, in denen es erforderlich ist, die Liste der Zuordnungsschlüssel zu haben. Es gibt zwei Möglichkeiten, eine solche Liste zu erstellen: 1 indem Sie alle vorhandenen Elemente in der Liste auf Duplikate prüfen, bevor Sie den Eintrag hinzufügen, 2 das Mapping vor dem Ändern prüfen, ob der Wert am Schlüssel 0 ist. Wenn 0, dann kann der Schlüssel "könnte „neu sein.
@RFVenter. Die obige Antwort behandelt die gestellte Frage und zeigt auch eine Möglichkeit, Schlüssel in Zuordnungen zu verfolgen. "Überprüfe alle vorhandenen Mitglieder in der Liste" ist möglicherweise falsch angegeben? Es wäre katastrophal, alle Schlüssel in einer Liste von n Zeilen (Anti-Pattern) zu iterieren. Zuordnungen hingegen bieten keine Möglichkeit, die Schlüssel aufzuzählen. Wirklich nicht sicher, was Sie meinten.