Wavelet v0.1.1 – Perlin

Después de lanzar el primero Versión beta de Wavelet Hace un mes, hemos estado optimizando continuamente tanto el diseño del protocolo como la implementación para hacerlo más rápido, más seguro y más amigable para el desarrollador.

En base a nuestra discusión interna y los comentarios de la comunidad, se implementaron varias características y correcciones importantes en Wavelet v0.1.1, que incluyen:

tarifas de gas de crowdsourcing para contratos inteligentes,Soporte de contrato inteligente de AssemblyScript,Autocompletado de CLIyreglas de inicio de transacciones más seguras.

Nuevas características y correcciones importantes

https://github.com/perlin-network/wavelet/releases/tag/v0.1.1

Cuando una transacción en cadena invoca un contrato inteligente, hay un costo para ejecutar el contrato y el costo debe ser pagado por alguna cuenta. El costo se llama gas y la moneda virtual pagada es la tarifa de gas.

Por lo general, la cuenta que envía la transacción de solicitud de contrato tiene que pagar la tarifa de gas. Pero esa no es la única opción para asegurarse de que las tarifas de gas estén cubiertas. Por ejemplo, el usuario de un contrato puede participar en tarifas de gas de crowdsourcing transfiriendo dinero al contrato balance de gases, y los usuarios legítimos, una vez identificados, pueden deducir sus tarifas de gas del saldo de gas de crowdsourcing en lugar de pagar por sí mismos.

Wavelet v0.1.1 implementa crowdsourcing, y esperamos que el método de pago flexible para las tarifas de gas pueda beneficiar a más desarrolladores y usuarios de contratos.

Antes de v0.1.1, el único lenguaje de contrato inteligente que admitimos para Wavelet es Rust. Recientemente decidimos agregar soporte oficial para más idiomas, incluido AssemblyScript.

Rust compila a WebAssembly a través de LLVM, mientras que AssemblyScript usa su propio backend de generación de código. Entonces, hay bastantes diferencias en el código generado. Para admitir los patrones utilizados por AssemblyScript, realizamos algunos cambios en el motor de contrato inteligente de Wavelet.

Llamando a la función de inicio en la inicialización

De acuerdo con las especificaciones de WebAssembly, una función de inicio es la función de "inicializador" que debe llamarse cuando se carga un módulo.

Todas las variables globales en Rust son inicializado estáticamente en tiempo de compilación o perezosamente inicializado – Esto significa que no hay necesidad de una función de inicio. Sin embargo, AssemblyScript inicializa todas las variables globales no triviales en la función de inicio. Las rutinas para llamar a la función de inicio se agregaron a Wavelet en v0.1.1.

Preservando los globales

Globales en WebAssembly son similares a las variables globales en los lenguajes de programación de nivel superior. El conjunto de globales y la memoria lineal componen el estado persistente que debe preservarse en las invocaciones de contratos inteligentes.

Sin embargo, solo la memoria lineal se conservó antes de Wavelet v0.1.1. Esto no causó ningún problema para los contratos inteligentes de Rust / LLVM porque LLVM solo usa globales para puntero de pila lineal, que no necesita conservarse en las invocaciones. AssemblyScript usa globals también para variables globales a nivel de lenguaje, por lo que también debemos preservar los globales. En v0.1.1, los globales se guardan con una clave diferente en el estado de la cuenta y se vuelven a cargar en cada invocación de contrato, lo que soluciona el problema.

Hay dos formas de interactuar con un libro mayor de Wavelet en ejecución: a través de la API HTTP y directamente a través de la interfaz de línea de comandos (CLI).

En v0.1.1, agregamos autocompletado apoyo a la CLI. Eso significa que puede ingresar un prefijo de comandos, opciones e incluso ID de transacciones, y simplemente presionar TAB para que se complete automáticamente.

Autocompletado

Reducción de asignaciones y expresión de inmutabilidad en Go

El rendimiento es importante para Wavelet. Wavelet está escrito en Go, un lenguaje de alto nivel con un recolector de basura y automático análisis de escapey, por lo tanto, necesitamos trabajar con estas características de dos idiomas correctamente para lograr el mejor rendimiento.

Mientras tanto, limpieza sintáctica También es importante asegurar que nuestra base de código se pueda mantener adecuadamente. Por lo tanto, pasamos algunos objetos por valor para expresar "inmutabilidad", aunque Go no tiene un optimizador lo suficientemente bueno como para eliminar todas las copias de memoria.

Hicimos muchos puntos de referencia y análisis para equilibrar el rendimiento y la limpieza, y el trabajo resultó en PR # 132.

Como se presentó en publicaciones anteriores, transacción crítica es una parte fundamental de nuestro protocolo de consenso. los semilla de una transacción es un valor de 256 bits que se usa para determinar la importancia de una transacción de manera similar a cómo funcionan los hashes PoW, contando el número de ceros de prefijo.

Antes de v0.1.1, la semilla de una transacción fue calculada por:

blake2b_256 (
sender_id +
concat (sorted_parent_seeds)
)

Al agregar algunas restricciones adicionales en la ID del remitente (apuesta mínima), este algoritmo es resistente a la "minería". Solo puede probar nuevas semillas enviando nuevas transacciones, por las cuales debe pagar tarifas de transacción.

Aunque se ve bien a primera vista, esto presenta un problema que puede ser explotado para realizar ataques DoS en la red. Una vez que se encuentra una semilla, la semilla puede usarse para crear una cantidad infinita de transacciones críticas sin costo, siempre y cuando tengan los mismos padres.

Una posible forma de solucionar el problema es agregar un hash corto del contenido de la transacción al proceso de cálculo de la semilla, de modo que la semilla de la transacción se calcule de la siguiente manera:

blake2b_256 (
sender_id +
concat (sorted_parent_seeds) +
short_hash (contenido de transacción)
)

Esto aumenta la dificultad de reutilizar una semilla crítica y se implementa en v0.1.1 con hashes cortos de 8 bits. Con un tamaño suficiente para los hashes cortos, la propiedad de resistencia PoW de las semillas de transacción aún se conserva, y la presión de la reutilización crítica de semillas se puede descargar del protocolo de consenso en caso de actividad maliciosa.

¿Qué vendrá pronto?

Soporte completo de sincronización de estado / transacción. Cuenta nonces para soporte estricto de orden de transacción y reenvío seguro.