mapeo con matriz de estructura, gas o problema de rendimiento?

Tengo una pregunta sobre la iteración de un mapeo con matriz de estructura. Hay un bucle for que itera unas miles de veces tratando de encontrar propiedades coincidentes dentro de la estructura.

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
}

Esta iteración no está dentro de una función viewnor constant. Así que consume algo de gasolina mientras lo llama. Solo me preocupa que la función se esté quedando sin gas si el ciclo itera sobre un gran número (¿más de diez mil?)

¿Hay alguna sugerencia en términos de optimización?

Respuestas (2)

Esta solución te permitirá evitar bucles, lo que en tu aplicación podría ser catastrófico ya que el contrato podría estancarse si hay muchos usuarios y el gas necesario para el bucle supera el límite permitido. Traté de mantenerlo lo más cerca posible de su implementación original:

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

mapping(uint => MatchBettingInfo) public matchBettingInfo;  

Ahora, establecer una apuesta será implementado por esta función:

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

Ahora puede obtener una lista de los ganadores de una sola vez:

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

}

¿Cómo funciona esto?

Primero, tenga en cuenta que el mapeo ahora es un mapeo de estructura y no un mapeo de una matriz de estructuras.

Los ganadores deben adivinar tanto el marcador local como el visitante, entonces esta es una combinación única, guardo el hash de los dos números como apuesta. La estructura también guarda estos números para cada dirección en caso de que necesite tenerlos, si no los tiene, es seguro eliminar estos dos mapeos llamados awayScoreyhomeScore

Ahora bien, obtener la cantidad de ganadores es tan simple como obtener la cantidad de direcciones almacenadas en la clave que se forma al obtener el hash de homeScorey awayScore.

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

Darle el número de ganadores y:

matchBettingInfo[_matchId].bets[winnerScore]

te dará la lista de ganadores de una sola vez!!!

Espero que esto ayude

impresionante implementación! Tengo una pregunta. Dado que la estructura contiene solo los tipos indexados, no puede declarar la variable de estado matchBettingInfocomo public. Necesito obtener la longitud de cuántas personas apostaron por elmatchId
Está bien. Acabo de incluir uint totalNumOfBetters;en la estructura e incluir matchBettingInfo[_matchId].totalNumOfBetters += 1;en la makeBetfunción. De esta manera pude recuperar la duración de cuántas personas apostaron por el particular matchId. Si tiene una idea mejor, por favor avise. Voy a marcar esto como una respuesta. Gracias.
Creo que eso servirá.

¿Por qué la fuente usa un mapeo de mapeo en lugar de una matriz indexada? El método que mostró consume potencialmente una gran cantidad de gas, de una manera no predecible.

¿Podría dar algunos ejemplos, por favor?