¿Almacenamiento DApp para datos que no sean transacciones?

A modo ilustrativo, supongamos que me gustaría crear una versión descentralizada de Yelp.

Un enfoque centralizado sería tener una restaurantstabla y una reviewstabla en una base de datos Mysql. En el caso de una DApp, ¿cuál es la mejor práctica para almacenar datos no transaccionales?

Mi pensamiento actual es tener un Restaurant.solcontrato y un Review.solcontrato, cada uno con una asignación desde la identificación del registro como clave, hasta el objeto de registro como valor. Cada vez que se agrega un restaurante, invocamos un addRecord()método en Restaurant, que agrega los datos del nuevo restaurante a su asignación actual. (Flujo similar para Review)

¿Es robusto este enfoque de tratar un contrato como una tabla RDBMS? ¿O me estoy perdiendo algo?

¿Cuál es el límite de la cantidad de datos que se pueden almacenar en el mapeo de un contrato?

EDITAR: según tengo entendido, cambiar el mapeo del Restaurantcontrato costaría éter. Entonces, ¿eso significa que cada nuevo registro que se agrega a la "base de datos" cuesta dinero? ¿Cuál es una forma económicamente viable de ejecutar una aplicación sin que los usuarios paguen?

Por favor avise.

¿Has mirado IPFS: ipfs.io?

Respuestas (2)

Primero, no querrá pensar en los contratos como algo análogo a las tablas. Cada contrato puede contener múltiples asignaciones de información. Podría tener un solo ReviewSystem.sol que tenga asignaciones tanto para Restaurantes como para Reseñas y, de acuerdo con lo que sugirió anteriormente, podría tener métodos addRestaurant()que addReview()agregarían registros a las asignaciones almacenadas en el contrato.

Dicho esto, los contratos no tienen muy buenos mecanismos para datos relacionales normalizados. En una base de datos relacional, si tuviera un registro de "Restaurante", podría ejecutar una consulta para todas las reseñas relacionadas con un determinado restaurante, y con el poder de los índices y los planificadores de consultas recuperar esa información muy rápidamente. En Ethereum tus opciones son más limitadas. Si no tiene un índice, deberá escanear cada reseña en su sistema para ver si se relaciona con el restaurante en cuestión. Si tiene un índice, aumenta los costos de escribir registros en su contrato. También puede desnormalizar los datos para búsquedas más rápidas, nuevamente a costa de un mayor almacenamiento por contrato.

Una opción es mantener parte de su información fuera de la cadena. Por ejemplo, puede mantener sus restaurantes y reseñas en su contrato con un puntero de Reseña a Restaurante. Por separado, puede tener una base de datos tradicional que indexe la relación de Reseñas a Restaurantes. Cuando alguien agrega una reseña a través de su DApp, el contrato almacena la información canónica y la base de datos separada guarda una copia de la información. Cuando alguien quiere buscar las reseñas relacionadas con un determinado restaurante, puede consultar una API respaldada por la base de datos que puede devolver rápidamente las identificaciones de las reseñas, y puede obtener las reseñas por sí mismo de la cadena de bloques. En este caso, toda la información crítica está disponible en la cadena y el índice fuera de la cadena se puede reconstruir a partir del estado del contrato. Para obtener información sobre el seguimiento de eventos de contrato fuera de la cadena,Eventos y registros .

Como anotó en su edición, cada pieza de información que guarde en un contrato cuesta gasolina, y esa gasolina a su vez cuesta Ether. Ejecutar un servicio como Yelp con cientos de miles de negocios y reseñas de miles de palabras podría resultar muy costoso. Podría mitigar algunos de los costos almacenando más información fuera de la cadena. Tal vez una revisión en cadena consiste en una calificación de estrellas y el hash de la revisión escrita, luego el texto de la revisión se recupera de una fuente fuera de la cadena, como la base de datos que discutimos anteriormente, o quizás otro sistema descentralizado como ipfs.

Sin embargo, en general, veo la cadena de bloques de Ethereum como el lugar donde almacena información que no desea confiar en terceros para administrar. Cosas como los tokens ERC20, ENS y los intercambios distribuidos son un excelente caso de uso porque, de lo contrario, sería difícil establecer confianza en una entidad centralizada. Si bien sería bueno tener algo como un servicio de revisión descentralizado, el costo del almacenamiento por contrato, combinado con el riesgo relativamente bajo de confiar en un tercero para administrar esa información, lo convierte en un caso de uso menos atractivo para la cadena de bloques.

Primero, para responder a sus preguntas:

"¿Este enfoque de tratar un contrato como una tabla RDBMS es robusto? ¿O me estoy perdiendo algo?"

Sí, esta solución es robusta , suponiendo que quiera decir confiable o "funcionará siempre". De hecho, la solidez es uno de los rasgos más atractivos de la redacción de contratos que se ejecutan en la cadena de bloques de Ethereum: tiene más redundancia de la que nadie podría necesitar. Hay 25,5xxnodos [ 1 ] ahora mismo. Cada uno de esos nodos almacena una copia de sus datos, su código y ejecuta cada línea de código en su contrato.

"¿Cuál es el límite de la cantidad de datos que se pueden almacenar en el mapeo de un contrato?"

Esta pregunta es respondida aquí por una figura autorizada en la comunidad de Ethereum, por lo que me abstendré de abordarla, excepto para decir que probablemente no tenga tantos datos o que ciertamente no pueda permitirse el lujo de almacenar tanto como la cadena de bloques". tomar". Dicho esto, dado que cada nodo almacena una copia de los datos de la cadena de bloques, si pudiera permitírselo, sobrecargaría cada uno de los nodos y posiblemente haría que existieran menos nodos, ya que ejecutar un nodo costaría más porque el tamaño de los datos sería muy enorme.

"Según tengo entendido, cambiar el mapeo del contrato del restaurante costaría éter. ¿Eso significa que cada nuevo registro que se agrega a la "base de datos" cuesta dinero?"

Sí, cambiar el mapeo está cambiando el estado de la cadena de bloques, por lo que costará gasolina.

¿Cuál es una forma económicamente viable de ejecutar una aplicación sin que los usuarios paguen?

Tienes pocas opciones:

  1. ~~Cargue la gasolina a sus usuarios~~
  2. Compensa a tus usuarios con unidades adicionales de tu token de aplicación nativo, si tienes un suministro flexible de tu token
  3. En la organización a la que contribuyo, almacenamos un hash que es una prueba criptográfica de los datos fuera de la cadena y almacenamos solo el hash de IPFS en la cadena. Desafortunadamente, los hashes de IPFS son más que la palabra EVM de 32 bytes (consulte esta respuesta altamente informativa sobre el almacenamiento de hashes de IPFS en cadena en una estructura).
    • Lo interesante de esta solución es que los usuarios pueden verificar más tarde de forma independiente que los datos a los que apunta el hash son los que realmente deberían haberse almacenado en la cadena ejecutando la misma función hash en los datos devueltos.

Conclusiones del almacenamiento de datos de Ethereum/Dapp

  • El almacenamiento de datos en cadena es muy costoso en comparación con las soluciones centralizadas.
  • Almacenar 1 kB cuesta 640,000gas
  • 640,000costos de gas $0.08: $0.90utilizando los precios actuales de éter según la rapidez con la que desea que se extraiga/confirme su transacción
  • Si el precio del éter continúa aumentando, el precio de almacenar sus datos aumentará con él, suponiendo que no ocurra una disminución proporcional en el precio del gas aceptado que los mineros están dispuestos a aceptar.
  • Cada cambio en la cadena de bloques, por pequeño que sea, cuesta gasolina (o "dinero" en el lenguaje heredado)

    • Por ejemplo, enviar ether con el send()método incorporado cuesta 21,000gas
    • Del papel amarillo 4 : Gtransaction 21000 Paid for every transaction.Entonces, cada tx cuesta al menos 21,000, ese es el costo mínimo
  • Sin embargo, obtener datos de la cadena de bloques es gratis:

    • Podemos obtener datos de la cadena de bloques de varias maneras:
      • Funciones getter que se crean automáticamente para nosotros para cada publicvariable en nuestros contratos
        • Por ejemplo, la línea: uint public numRestaurants = 42;crea una función que podemos llamar desde nuestro contratothis.numRestaurants()
        • En web3cliente podríamos llamar a esta función concontractInstance.numRestaurants.call()
      • Se pueden declarar funciones de contratoconstant que prometen no modificar estado o viewfunciones
        • function f(uint a, uint b) view returns (uint) { return a * (b + 42) + now; // does math but doesn't change state! }
      • Los eventos son datos que se almacenan en la cadena de bloques.
        • LogUpdateRestaurant('mandalay', 8.7, 'restaurant')en la función que almacenará los datos de tu restaurante
        • Definimos eventos conevent LogUpdate(indexed string restaurantName, uint8 rating, TypeEnum type);

    Compartiré más sobre cómo nos hemos acercado al almacenamiento de nuestros datos en una aplicación casi completamente descentralizada en una fecha posterior. Y gracias por enseñarme lo que aprendí al escribir esta respuesta (como viewahora es un alias para constant)