Membresía en un conjunto de cadenas

Estoy buscando ayuda de solidez para almacenar un conjunto de cadenas y verificar la membresía en ese conjunto. Tengo una pregunta concreta y otra abstracta sobre eso:

Concreto

¿Cuál es la estructura de datos en Solidity que me brinda un conjunto (potencialmente solo para agregar) que puedo interrogar para ser miembro? por ejemplo, estoy buscando específicamente algo como:

myset = ["a", "b", "c"] # registers my set on-chain
"d" in myset            # return True or False

Además, ¿existen formas mejores o peores de usar esta estructura de datos sin mucha duplicación de datos?

¿Cambia la respuesta si mysettiene un millón de miembros?

Abstracto

¿Cómo se implementa tal cosa bajo el capó? Las pruebas de acceso de lectura para membresía parecen posibles, pero dado que las cadenas son inmutables, ¿cómo se actualizaría en la práctica esa lista?

Respuestas (1)

A mappinges todo lo que necesitas:

pragma solidity ^0.4.25;

contract Test { 
    mapping(string => bool) seen;

    function add(string foo) external {
        seen[foo] = true;
    }

    function alreadySeen(string foo) external view returns (bool) {
        return seen[foo];
    }
}

El almacenamiento por contrato es mutable. Llamar a la cadena de bloques "inmutable" es quizás engañoso... un término mejor podría ser "solo añadir". Al enviar nuevas transacciones a un contrato inteligente, puede agregarlas a la cadena de bloques y el estado en el último bloque puede ser diferente al estado en los bloques anteriores. Entonces, todos los bloques antiguos todavía están allí y son inmutables, pero el estado actual del almacenamiento de su contrato inteligente puede ser diferente con el tiempo (porque "actual" significa el último bloque).

Tenga en cuenta que las claves de a mappingno se pueden enumerar. Si necesita enumerar los valores que agregó a su conjunto, tengo una publicación de blog sobre conjuntos enumerables que debería ayudar: https://programtheblockchain.com/posts/2018/06/03/storage-patterns-set/ .