Consulta del estado del contrato

Puede ver el estado de un contrato como cliente externo utilizando la CLI o mientras ejecuta otro contrato. En esta sección, exploraremos los dos tipos de consultas: sin procesar y personalizadas. También veremos la semántica de la consulta a través de un cliente externo y como cliente interno (otro contrato). Prestaremos especial atención no sólo a cómo funciona en la práctica, sino también a las cuestiones de diseño y seguridad de la ejecución de consultas de un contrato a otro.

Consultas en bruto

La consulta más sencilla de implementar es el acceso de lectura sin procesar al almacén de valores clave. Si la persona que llama (ya sea un cliente externo u otro contrato) pasa la clave binaria en bruto utilizada en el almacenamiento del contrato, podemos devolver fácilmente el valor binario en bruto. La ventaja de este enfoque es que es fácil de implementar y universal. La desventaja es que requiere conocer el contrato exacto que se está ejecutando, ya que espera que la persona que llama conozca la implementación del almacenamiento del contrato.

Dado que las consultas sin procesar se implementan dentro del tiempo de ejecución de wasmd, evitan la máquina virtual. Como consecuencia, no requieren soporte del contrato CosmWasm, y todo el estado del contrato es visible. La función query_raw está expuesta a todas las llamadas, tanto externas como internas.

Consultas personalizadas

Como a menudo no es deseable acoplarse estrechamente a los detalles de implementación, es preferible depender de una interfaz en su lugar. Por ejemplo, podemos definir un estándar para "CW20" ExecuteMsg para llamar al contrato, y podemos definir tal estándar para un QueryMsg también. Por ejemplo, consultar el saldo por dirección, consultar el subsidio a través del otorgante + el beneficiario y consultar la información de las fichas (ticker, decimales, etc.). Al definir una interfaz estándar, permitimos muchas implementaciones, incluyendo contratos complejos, donde la interfaz "CW20" es sólo un pequeño subconjunto de su funcionalidad.

Para habilitar las consultas personalizadas, permitimos que cada contrato exponga una función de consulta que pueda acceder a su almacén de datos en modo de sólo lectura. Esto permite cargar cualquier dato e incluso realizar cálculos sobre él. Este método se expone como query_custom a todas las llamadas, tanto externas como internas. Como el formato de los datos (tanto para la consulta como para la respuesta) puede ser el que desee el contrato, debe documentarse en el esquema público, junto con ExecuteMsg e InitMsg.

Tenga en cuenta que la ejecución de un contrato puede consumir una cantidad ilimitada de gas, mientras que query_raw leerá una clave y tiene un coste pequeño, en su mayor parte fijo. Con query_custom, necesitamos imponer un límite de gas. Como el método para imponer un límite de gas se hace de forma diferente para las llamadas externas e internas, profundizaremos en los detalles a continuación.

Consultas externas

Las consultas externas son la principal forma en que los clientes web y CLI interactúan con el blockchain. Hacen una llamada a Tendermint RPC, que a su vez llama a abci_query en el SDK de Cosmos y delega la tarea al módulo apropiado. Para evitar posibles vectores de ataque, como el uso de un contrato wasm con un bucle infinito para crear un ataque DoS en un nodo RPC público que expone la consulta, es necesario definir un límite de gas fijo para todas las transacciones query_custom llamadas externamente. Este límite no se utiliza para cobrar una tarifa, sino para limitar los abusos.

Sin embargo, es difícil definir un valor estándar para el límite de gas, ya que un nodo expuesto públicamente probablemente establecería un límite de gas pequeño, mientras que un nodo de archivo que realice consultas complejas requeriría un valor diferente. Para solucionar este problema, se puede definir un límite de gas para todas las llamadas query_custom en un archivo de configuración específico de la aplicación. Los operadores de nodos pueden personalizar este valor, mientras que se establece un límite por defecto razonable para permitir que los nodos públicos se protejan de las consultas complejas. Las consultas opcionales pueden realizar grandes agregaciones sobre todos los datos de contratos en nodos especialmente configurados.

Es importante tener en cuenta que la llamada abci_query nunca lee el estado actual "en curso" de los módulos. En su lugar, utiliza una instantánea de sólo lectura del estado después del último bloque confirmado.

Consultas internas

Aunque muchas interacciones entre contratos pueden modelarse fácilmente mediante el envío de mensajes, hay algunos casos en los que nos gustaría consultar de forma sincrónica otros módulos sin alterar su estado. Por ejemplo, si quisiéramos resolver un nombre a una Dirección, o si quisiéramos comprobar el estado de alguna cuenta antes de activar una acción. Aunque podrías modelar esto como una serie de mensajes, sería bastante complejo y crearía problemas a la hora de implementar casos de uso sencillos.

Nótese que este diseño también violaría uno de los principios básicos del Modelo Actor, ya que cada contrato sólo debería tener acceso exclusivo a su propio estado interno. Tanto query_raw como query_custom fallan en este aspecto. Lejos de ser sólo un problema teórico, esto puede llevar a problemas de concurrencia y reentrada si no se maneja correctamente. Como no hay necesidad de poner este razonamiento de seguridad crítica en manos de los desarrolladores de contratos, las garantías de seguridad se pueden incrustar en el propio marco.

Como tal, proporcionamos al Querier acceso de sólo lectura a la instantánea del estado justo antes de la ejecución del mensaje CosmWasm actual. Dado que tomamos una instantánea y tanto el contrato en ejecución como el contrato consultado tienen acceso de sólo lectura a los datos antes de la ejecución del contrato, esto sigue siendo seguro debido a las reglas de préstamo de Rust. El contrato actual sólo escribe en una caché, que se vacía después en caso de éxito.

Tenga en cuenta que todas las consultas se realizan como parte de una transacción, que ya tiene un límite de gas fuertemente impuesto. Todas las lecturas de almacenamiento y el procesamiento de datos realizados como parte de una consulta se deducen del mismo contador de gas que el resto de la transacción y, por tanto, limitan el tiempo de procesamiento.

Last updated