Zuordnung mit Struct-Array, Gas- oder Leistungsproblem?

Ich habe eine Frage zum Iterieren eines Mappings mit einem Struct-Array. Es gibt eine for-Schleife, die einige tausend Mal wiederholt wird, um eine übereinstimmende Eigenschaft innerhalb der Struktur zu finden.

Ex:

struct MatchBettingInfo {    
    address better;
    uint matchId;
    uint homeScore;
    uint awayScore; 
}

mapping(uint => MatchBettingInfo[]) public matchBettingInfo;  

function claimPrizes(uint _matchId, uint _homeScore, uint _awayScore) public returns (bool) {
    uint totalNumBetters = matchBettingInfo[_matchId].length;  

    // Find matching scores among betters who betted for this match
    for (uint i = 0; i < totalNumBetters; i++) {
        if (matchBettingInfo[_matchId][i].homeScore == _homeScore && 
            matchBettingInfo[_matchId][i].awayScore == _awayScore) {          
            numOfWinners++;
        }  
    }  

    ... more codes
}

Diese Iteration befindet sich nicht in einer viewNor- constantFunktion. Es nimmt also beim Rufen etwas Gas auf. Ich mache mir nur Sorgen, dass der Funktion das Gas ausgehen könnte, wenn die Schleife über eine große Zahl (über Zehntausende?)

Gibt es Optimierungsvorschläge?

Antworten (2)

Mit dieser Lösung können Sie Schleifen vermeiden, die in Ihrer Anwendung katastrophal sein könnten, da der Vertrag hängen bleiben könnte, wenn viele Benutzer vorhanden sind und das für die Schleife erforderliche Gas die zulässige Grenze überschreitet. Ich habe versucht, es so nah wie möglich an Ihrer ursprünglichen Implementierung zu halten:

struct MatchBettingInfo {    
    mapping(bytes32 => address[]) bets;
    mapping(address => uint) homeScore;
    mapping(address => uint) awayScore; 
}

mapping(uint => MatchBettingInfo) public matchBettingInfo;  

Nun wird das Setzen einer Wette durch diese Funktion implementiert:

function makeBet(uint _matchId, uint _homeScore, uint _awayScore) public {
    bytes32 mybet = keccak256(_homeScore,_awayScore);
    matchBettingInfo[_matchId].bets[mybet].push(msg.sender);
    matchBettingInfo[_matchId].homeScore[msg.sender] = _homeScore;
    matchBettingInfo[_matchId].homeScore[msg.sender] = _awayScore;
}

Jetzt können Sie auf einen Schlag eine Liste der Gewinner erhalten:

function claimPrizes(uint _matchId, uint _homeScore, uint _awayScore) public returns (bool) {
    bytes32 winnerScore = keccak256(_homeScore,_awayScore);
    uint numOfWinners = matchBettingInfo[_matchId].bets[winnerScore].length;

    // rest of your code

}

Wie funktioniert das?

Beachten Sie zunächst, dass die Zuordnung jetzt eine Zuordnung von Structs und keine Zuordnung eines Arrays von Structs ist.

Die Gewinner müssen sowohl das Heim- als auch das Auswärtsergebnis erraten, dann ist dies eine eindeutige Kombination, ich speichere den Hash der beiden Zahlen als Wette. Die Struktur speichert diese Nummern auch für jede Adresse, falls Sie sie benötigen, wenn Sie dies nicht tun, können Sie diese beiden Zuordnungen namens awayScoreund sicher entfernenhomeScore

Nun, um die Anzahl der Gewinner zu ermitteln, ist es so einfach, die Anzahl der Adressen zu ermitteln, die in dem Schlüssel gespeichert sind, der durch Abrufen des Hashs von und gebildet homeScorewird awayScore.

uint numOfWinners = matchBettingInfo[_matchId].bets[winnerScore].length;

Geben Sie die Anzahl der Gewinner an und:

matchBettingInfo[_matchId].bets[winnerScore]

gibt Ihnen die Liste der Gewinner auf einen Schlag!!!

Hoffe das hilft

tolle umsetzung! Ich habe eine Frage. Da die Struktur nur die indizierten Typen enthält, kann sie die Zustandsvariable nicht matchBettingInfoals deklarieren public. Ich muss wissen, wie viele Leute darauf gewettet habenmatchId
In Ordnung. Ich habe gerade uint totalNumOfBetters;in die Struktur eingeschlossen und matchBettingInfo[_matchId].totalNumOfBetters += 1;in die makeBetFunktion eingeschlossen. Auf diese Weise konnte ich die Länge abrufen, wie viele Leute für die jeweilige Wette gewettet haben matchId. Wenn Sie eine bessere Idee haben, raten Sie bitte. Ich werde dies als Antwort markieren. Danke.
Ich denke, das wird reichen.

Warum verwenden Schriftarten eine Zuordnung von Zuordnungen anstelle eines indizierten Arrays? Die von Ihnen gezeigte Methode verbraucht auf nicht vorhersehbare Weise möglicherweise viel Gas.

Könnten Sie bitte einige Beispiele geben.