Cómo vimos los pagos de IoT en un hackathon en Hong Kong


El 10 de junio fue el tercer día de nuestra aclimatación en Hong Kong. Y las últimas 26 horas pasamos casi sin dormir, desarrollando un proyecto prototipo bajo el nombre de trabajo SensorPay en la primera etapa del hackathon EOS Global con un premio total de un millón y medio de dólares. Se acercaba el momento de la demostración del proyecto ante los jueces.


Si está ansioso por saber cómo terminó esta historia, eche un vistazo a la última parte de inmediato. Mientras tanto, comenzaremos a hablar sistemáticamente sobre las tecnologías EOS y cómo surgió la idea de vincular los pagos de IoT a EOS. Justo después de eso, habrá una descripción detallada del relleno técnico del proyecto.


0. Antecedentes


EOS es una cadena de bloques de nueva generación, algunos incluso lo consideran un asesino de Ethereum. Si de repente no sabes qué es una cadena de bloques o Ethereum, Google te ayudará. Y, sucedió, comenzamos a desenterrar EOS hace aproximadamente un año, incluso mediante el estudio de los productos anteriores de sus autores BitShares y Steem.


Las ventajas de EOS en comparación con Ethereum: el rendimiento de la transacción es tres órdenes de magnitud mayor; sistema de permisos desarrollado para contratos inteligentes; la capacidad de restaurar el acceso perdido y corregir errores en la cadena de bloques; gestión de redes onchain. Debilidades: preocupaciones de centralización, consenso DPoS potencialmente más vulnerable, código sin procesar y una curva de aprendizaje más pronunciada para los desarrolladores.


Como nos ha gustado esta tecnología durante mucho tiempo y la consideramos prometedora, no podemos ignorar la serie de hackatones, que cuentan con el respaldo de los autores de EOS. Solo queríamos estar allí, realizar nuestras ideas en este entorno inspirador y compartirlas con una amplia audiencia. Por supuesto, la oportunidad de ganar buen dinero también se convirtió en un motivador agradable adicional.


Entonces, EOS es la única solución de trabajo para la cadena de bloques pública que sabemos dónde puede hacer MUCHAS transacciones. ¿Dónde se requiere? ¡Por supuesto en IoT! De hecho, si cada tostadora se convierte en micropagos, pagará por cada pieza de pan al refrigerador (y esto es genial por defecto, como comprenderá), habrá muchas transacciones. Sin mencionar todo tipo de otras aplicaciones en medicina, industria y vida cotidiana.


Unas semanas antes del hackatón, periódicamente surgían ideas alternativas y se realizaban pequeñas tormentas de ideas. Comparamos ideas sobre la base de criterios de arbitraje bien conocidos: el uso de capacidades EOS, creatividad, impacto público y escalabilidad. Como resultado, nos decidimos por IoT + EOS, una solución que tomaría datos de los sensores y enviaría muchas transacciones de pago a EOS.


Por cierto, realmente queríamos contar también aquí cómo criamos a nuestro productor de bloques para EOS; cómo planearon eliminar para él el constructor de tokens similares a ERC721 y soporte para funciones constantes; ¿Cómo presentaron el protocolo Merkle Root ACL? Pero todo esto no cabe en el artículo, por lo que volveremos a nuestro proyecto principal.



1. Preparación


1.1. IoT


Preparar la parte de IoT del proyecto es elegir el hardware adecuado. En el papel del lector RFID, se eligió el RC522 que opera en el bus SPI: es popular y fácil de usar.



Al buscar un contador, nos enfocamos en la presencia de una salida de pulso, ya que le permite leer los datos de manera muy simple: un pulso es X kW⋅h (donde X depende del modelo), como resultado, nos detuvimos en el contador Mercury 201.5.



Lo más difícil fue decidir sobre el controlador, que debería recopilar datos de los sensores, formar una transacción, firmarlo con su clave privada y enviarlo a la red. En consecuencia, necesitábamos un dispositivo con un módulo de red que pudiera firmar una transacción usando ECDSA (en este caso, en la curva elíptica secp256k1, ya que se usa en EOS para firmar).


Inicialmente, la elección recayó en el microcontrolador ESP8266, tiene un módulo Wi-Fi y todas las interfaces necesarias para conectar nuestros sensores. Al mismo tiempo, es muy compacto. Pero ninguno de los firmware tiene una implementación nativa de primitivas elípticas. Es posible escribir su propia implementación, pero esta no es una tarea para el hackathon. Como resultado, se eligió Raspberry Pi 3 B para el prototipo, y la biblioteca eosjs se utilizó para generar y firmar transacciones.



1.2. La infraestructura


Un par de días antes del hackathon, preparamos localmente y en el servidor eos-hackathon.smartz.io un ensamblado EOS ( fuente ). La instalación, el ensamblaje y las pruebas de dependencia fueron sorprendentemente fáciles para un proyecto tan joven (usando documentación ). No había suficiente tiempo para otra preparación de infraestructura, y ya tuve que lidiar con eso durante el hackathon.


1.3. Arquitectura


En vísperas del hackathon, discutimos la arquitectura y aclaramos los detalles del producto. Íbamos a implementar los siguientes casos principales: pagos por electricidad y pagos por compras marcadas con etiquetas RFID. También planearon hacer que el producto sea fácilmente extensible y usarlo en otras áreas.



La idea de la arquitectura es que el proveedor de servicios (Productor) crea un contrato: el punto central de interacción entre el proveedor y los consumidores. Cada consumidor tiene su propio saldo, que puede reponerse, los fondos se debitan de él en función de las señales del sensor. Todos los datos (usuarios, sensores, estadísticas) se almacenan en el contrato del proveedor.


Las preferencias del usuario están asociadas con el consumidor o las banderas (por ejemplo, una categoría de usuario preferencial): user_meta . Se pueden conectar varios sensores con el consumidor, para cada uno de ellos se indica un contrato y la configuración de facturación ( billing_meta ). Por lo tanto, puede obtener un contrato de facturación sin estado inmutable, que se utiliza para una gran cantidad de consumidores; los datos necesarios aparecerán durante la invocación del método de bill(payload, user_meta, billing_meta) . Además, se plantea la posibilidad de una lógica de facturación diferente, es decir, contratos diferentes: por ejemplo, uno considera la electricidad, el otro, los bienes. Cada sensor tiene un "puntero" a su contrato de facturación.


Se supone que el consumidor confía en el fabricante del sensor, pero no necesariamente confía en el proveedor del servicio. La interfaz de interacción con el sensor es extremadamente simple: es una llamada al método de contrato del proveedor con un parámetro numérico, que se transferirá a la facturación. El proveedor de servicios inicia a los consumidores, sensores, contratos de facturación y sus relaciones en su contrato, utilizando transacciones de control: establecedores primitivos. Cuando se recibe una transacción del sensor, se verifican los datos, se generan los datos de facturación, se llama a la facturación, se registra el pago y se registran las estadísticas.


Quizás, sobre todo, discutimos los siguientes temas que son importantes para la aplicabilidad del producto en el mundo real:


  • ¿Pagos iniciales o pospago? ¿Rellene su cuenta y úsela (como una conexión celular), o úsela y luego pague (como AWS)? Aquí no hay una respuesta correcta o incorrecta: diferentes empresas prefieren diferentes modelos. Para simplificar, decidimos aceptar pagos por adelantado.
  • ¿Debería el usuario mantener una cuenta separada para cada proveedor, o todos los cargos provienen de una cuenta? Nuevamente, no hay una decisión correcta o incorrecta; Además, la respuesta está estrechamente relacionada con la respuesta a la pregunta anterior. Los pagos por adelantado son buenos amigos con las cuentas individuales de los consumidores: se tomaron.
  • ¿Cobra una tarifa en EOS, una ficha de un proveedor de servicios o una moneda estable (vinculada a la moneda fiduciaria)? Las opciones distintas a la moneda estable, por supuesto, son inconvenientes para el consumidor debido a la volatilidad, y la moneda estable dentro del marco de EOS aún no existe. En ese momento, ¡incluso la red EOS principal no estaba allí! Por simplicidad, tomaron una ficha condicional.

2. Codificación


En primer lugar, especificaron la API y el marco del contrato del proveedor para comenzar simultáneamente el desarrollo de la interfaz, el código del dispositivo, la facturación y el contrato principal ( fuente ).


2.1. IoT


El primero en implementar un código para leer pulsos de un contador. Para trabajar con GPIO (pines de uso general), se utilizó la biblioteca onoff JS. Más tarde, se agregaron dos LED al circuito para mayor claridad: el primero parpadeó cuando se recibió una señal del contador y el segundo cuando una respuesta sobre una transacción exitosa vino del nodo EOS. Del mismo modo, desarrollamos un esquema y un código para leer etiquetas RFID, con la única diferencia: la lectura se realizó en el bus SPI utilizando la biblioteca MFRC522-python. Al final resultó que, la configuración de SPI para la Raspberry Pi 3 es diferente de la configuración en modelos de placa anteriores; Esta instrucción nos ayudó a entender.


Los dispositivos se alimentaron desde el banco de energía, que se presentó con éxito a todos los participantes del hackathon, y tuvieron que compartir Internet ellos mismos con el iPhone 5, ya que el wifi del hackathon funcionaba exclusivamente a 5 GHz, esto no funcionó para el Raspberry Pi.


2.2. Infraestructura y Utilidades


Los organizadores aconsejaron tomar la imagen del acoplador de eos-dev , pero estábamos confundidos por la falta de descripción y documentación de la imagen. En el servidor, continuaron trabajando con el ensamblaje preparado, y localmente, para evitar la instalación sistemática de EOS, usaron eos-dev.


Inmediatamente necesitaba urgentemente la capacidad de construir y probar rápidamente. Ideal: compila y ejecuta un archivo ejecutable localmente. Sin embargo, era imposible ignorar el hecho de que después del ensamblaje, la salida requería WebAssembly y, en el entorno EOS, con el impulso correspondiente, bibliotecas, contratos del sistema. Las opciones de compilación necesarias podrían verse en eosiocpp.in , sin embargo, decidimos no jugar a este juego. El resultado previsto, aunque un poco más lento, es más importante que una solución rápida con un rastrillo potencial. Por lo tanto, para el ensamblaje tomamos eoscpp, que está en el contenedor eos-dev.


Resultó ser más difícil con el lanzamiento, tuve que aumentar la cadena de bloques local EOS, y nuevamente no había una solución preparada. Solo software. Entonces apareció la primera versión de la infraestructura de lanzamiento. La idea es ocultar los matices de montaje y configuración y obtener un conjunto autoconsistente de cuatro a cinco "botones" para acciones típicas. Menos control, pero menos posibilidades de error, más ahorro de tiempo.


Los componentes principales de EOS incluyen los nodos, los demonios keosd, la utilidad de consola cleos y el compilador eoscpp:


  • nodeos - nodo EOS, daemon - participante de la red, proporciona acceso a la cadena de bloques y opcionalmente produce nuevos bloques;
  • keosd: un demonio para administrar billeteras locales que almacenan pares de claves;
  • cleos proporciona comandos desde la obtención de información sobre transacciones hasta el trabajo con claves; se implementa en función de llamadas en nodeos y keosd mediante la API HTTP;
  • eoscpp compila contratos en WebAssembly y también le permite obtener la interfaz binaria de la aplicación basada en el código fuente.

Inmediatamente se hizo evidente que los comandos cleos relacionados con las llamadas keosd no funcionaban. Dado que se emitió un error que indicaba la inaccesibilidad de la red keosd, pasamos tiempo diagnosticando problemas de red en la red acoplable. Sin embargo, strace mostró que no era la red: cleos accedía a la dirección incorrecta, siempre a localhost (y en el caso de nuestra infraestructura, diferentes demonios tienen diferentes direcciones de red en una red de acopladores separada). Se diagnosticó un error en cleos: la comprobación de la disponibilidad de keosd, que se realiza antes de cualquier comando relacionado con billeteras, tiene en cuenta el puerto pasado en los argumentos, pero no tiene en cuenta la dirección. Bajo el hackathon, cambiamos a la red host en Docker como una solución alternativa.


El siguiente paso fue la utilidad de compilación de contratos utilizando el compilador en el contenedor ( commit ). Se montaron directorios de entrada y salida. Y finalmente, la capacidad de subir un contrato a la cadena de bloques y enviar transacciones ( commit ). Una vez más: utilidades en un estilo consistente, simples "botones". Esto puso fin a la infraestructura básica, pero las sorpresas continuaron: nos topamos con el problema de las funciones C para trabajar con memoria (con más detalle a continuación).


En conclusión, comenzaron a configurar cuentas en un archivo (cada contrato y participante requieren cuentas separadas) junto con pares de claves que se crean automáticamente cuando comienza la cadena de bloques, para que un equipo pueda elevar el entorno de prueba. Se implementó una copia de este entorno en eos-hackathon.smartz.io.


2.3. Contratos inteligentes


2.3.1. Contrato de proveedores y facturación de electricidad.


Después del inicio del hackathon, comenzamos a diseñar la estructura de los contratos de acuerdo con el esquema anterior. El sistema constaba de los siguientes contratos:


  • supplier - contrato de supplier ;
  • billing_electricity : un contrato para calcular el pago de electricidad por cada tic del medidor.

En el contrato del supplier , la mayor parte del trabajo se lleva a cabo mediante operaciones CRUD ordinarias: agregando usuarios, tarifas, contadores, aumentando o disminuyendo el saldo del usuario. Los métodos más complejos fueron responsables de recibir datos del medidor, solicitar un contrato para calcular un pago (facturación), debitar la cuenta personal de un usuario después de una devolución de llamada de un contrato de facturación. El contrato de facturación necesario se determinó en función de la tarifa del usuario.


Después de la llamada en el contrato de facturación, se calculó el pago y se solicitó el método para debitar el pago de la cuenta personal del usuario. Habiendo lanzado la lógica principal, incluso pensamos si estábamos haciendo contratos demasiado simples. Un poco más tarde, después del despliegue de los contratos en el nodo y sus pruebas, quedó claro que los contratos pueden ser simples, pero hay matices. :)


Después del despliegue, resultó que las llamadas contractuales esperadas entre sí no funcionaron. No hay suficientes derechos. A diferencia de los contratos inteligentes en Ethereum, donde un contrato se llama desde un contrato en nombre del contrato de llamada, en EOS, toda la cadena comienza con el iniciador de la transacción. Cuando se llama a un contrato desde un contrato, se verifica si el iniciador permitió que el contrato hiciera esto.


Los mentores sugirieron inmediatamente cómo actuar en un caso simple. Los derechos se agregan de la siguiente manera (llamando al contrato inteligente del sistema eosio):


 ./cleos push action eosio updateauth '{"account":"electricity","permission":"active","parent":"owner","auth":{"keys":[{"key":"EOS7oPdzdvbHcJ4k9iZaDuG4Foh9YsjQffTGniLP28FC8fbpCDgr5","weight":1}],"threshold":1,"accounts":[{"permission":{"actor":"supplier","permission":"eosio.code"},"weight":1}],"waits":[]}}' -p electricity 

En este caso, la cuenta de electricity permite que el contrato del supplier llame a otros contratos en su nombre. Puede leer más sobre los derechos en Technical WP EOS . En nuestro país, el contrato del supplier causó el contrato de billing , y eso, a su vez, volvió a llamar al supplier . Agregar por analogía de derechos en este formulario no funcionó:


 ./cleos push action eosio updateauth '{"account":"electricity","permission":"active","parent":"owner","auth":{"keys":[{"key":"EOS7oPdzdvbHcJ4k9iZaDuG4Foh9YsjQffTGniLP28FC8fbpCDgr5","weight":1}],"threshold":1,"accounts":[{"permission":{"actor":"supplier","permission":"eosio.code"},"weight":1},{"permission":{"actor":"billelectro","permission":"eosio.code"},"weight":1}],"waits":[]}}' -p electricity 

Se emitió un error: autoridad no válida. Aquí los mentores ya no pudieron ayudarnos: dijeron que ellos mismos no hicieron esto. ¿Y quien lo hizo? Quizás solo Dan Larimer. No pudimos encontrar rápidamente la causa del error en el código EOS y ya hemos comenzado a considerar opciones alternativas, sin una cadena de llamadas. Se evitó maravillosamente que el mecanismo para llamar a otros contratos en EOS también sea diferente del éter. Cuando se llama a otro contrato, esta llamada se pone en cola y solo se completará después de que se complete la llamada actual. No funcionará llamar el contrato y después de la llamada leer los datos registrados por este contrato.


Más tarde, después de todo, encontraron en el código EOS la razón del error al establecer los derechos para dos contratos. Resulta que las cuentas en la lista de derechos deben ordenarse por cuenta: se asegura de que todas las claves sean únicas y estén ordenadas y que todos los permisos de la cuenta sean únicos y estén ordenados ( autoridad.hpp ). Después de cambiar el orden de las cuentas, la actualización de los derechos funcionó, y nuestro sistema de contratos comenzó a funcionar.


2.3.2. El problema de las funciones C con memoria


Es ridículo decirlo, pero al final no pudimos usar las funciones listas para analizar números (!) Para leer la configuración de facturación. Después de std::istringstream función std::istringstream , lo cual es bastante extraño. Y al usar atof y similares, así como sscanf - env.realloc ajustó. Por alguna razón, las funciones mencionadas de trabajar con la memoria de la biblioteca C estándar no se encontraron durante la carga de código en los nodos. Las funciones de C ++ que funcionan con la memoria funcionó.


Por supuesto, al ejecutar el contrato de WebAssembly, no se utiliza un asignador de memoria estándar, sino su propio entorno limitado, que se proporciona a cada transacción bajo ciertas condiciones. Además, el soporte para las funciones C de trabajar con memoria en la parte superior de este entorno limitado se ha implementado durante mucho tiempo, su implementación está en los contratos EOS estándar . Probablemente algo salió mal en la etapa de enlace.


Después de pasar aproximadamente una hora buscando una salida, incluso con la ayuda de uno de los mentores, decidimos no continuar y hacer una solución alternativa: escribir nuestro propio código que resuelva el problema de analizar números. El mecanismo EOS de flujo de datos no nos convenía: requería la capacidad de guardar paquetes de datos de diferentes estructuras en un campo y formarlos a mano (las configuraciones de facturación).


2.3.3. Facturación de compras


En el segundo viento, que fue abierto por los ingenieros de energía o por el desayuno temprano, escribieron la facturación de las compras en la tienda. El esquema general de trabajo es el siguiente:


  1. El proveedor crea un contrato de facturación y lo prescribe en su contrato general.
  2. En el punto de venta de la tienda, el proveedor establece marcos que pueden leer RFID, interactuar con EOS y tener sus propias cuentas prescritas en el contrato de facturación.
  3. Cada producto en la tienda está equipado con una etiqueta RFID, todas las etiquetas están registradas en el contrato de facturación.
  4. El comprador paga los bienes escaneando su RFID, y los bienes se eliminan del contrato de facturación.
  5. A la salida de la tienda, los marcos también leen las compras de RFID. Si los productos todavía están en la tienda, la transacción no pasa y el marco debe hacer sonar la alarma (sí, de hecho, ni siquiera puede enviar la transacción, solo lea la tabla).

No tiene sentido detenerse en el código del contrato en sí: este es C ++ 14 estándar con algunas construcciones y bibliotecas específicas de EOS. Mejor dicho en EOSIO Wiki y EOSIO Developer Portal .


2.3.4. Frontend


La parte frontal del proyecto se implementó usando React. En lugar de lo habitual, muchos Redux decidieron usar MobX, que acelera significativamente el desarrollo y le permite administrar el estado global sin dolor de cabeza.


La fase de integración de front-blockchain no fue tan fluida como se esperaba. El paquete eosjs se está finalizando de manera muy activa, seguido de la billetera EOS para el navegador Scatter . En este grupo, esto a menudo causa problemas. Y no el hecho de que el código que funcionó ayer funcionará bien hoy. Pisamos este rastrillo (y no la primera vez). Una hora de intentar y depurar en un estado somnoliento: el problema está resuelto.


Considere un diagrama simplificado de la interacción del lado del cliente de la aplicación con eos. Para hacer esto, necesita la biblioteca eosjs y la extensión del navegador Scatter.


¡Te lo recordamos! Scatter se actualiza activamente después de eosjs, no olvide actualizar la biblioteca.


A continuación, un breve vistazo a la lectura y la escritura. Hay dos formas de comunicarse con contratos inteligentes en EOS: el envío de transacciones (hace que la cadena de bloques se modifique, sin proporcionar valores de retorno) y las tablas de lectura (acción de solo lectura).


Considere el código de envío de la transacción:


  sendTransaction(funcName, data) { return this.scatter .suggestNetwork(this.network) .then(() => this.scatter.getIdentity({ accounts: [this.network] })) .then((identity) => { let accountName = this.getAccountName(identity); // wrap eos instance const eos = this.scatter.eos(this.network, Eos, this.configEosInstance); return eos.transaction(accountName, (contract) => { contract[funcName](data, { authorization: accountName }); }); }); } 

Argumentos de entrada: nombre y objeto de la función, sus valores son argumentos de esta función. Tercera línea: confirmamos la red a través de la cual interactuamos con EOS. Cuarta línea: obtenemos identity , el parámetro es un objeto con el campo de accounts (para esta red). La función getAccountName devuelve la primera cuenta de la lista de cuentas recibidas (en el objeto de identity ).


En este ejemplo, Scatter se usa para firmar una transacción. Scatter es un contenedor sobre una instancia de la clase Eos . En la línea 9, llamamos al método eos , sus parámetros:


  1. this.network : un objeto con parámetros de red.
  2. Eos es una instancia de eosjs.
  3. this.configEosInstance : un objeto con parámetros para una instancia de Eos (ver dock eosjs).

El último método de transaction acepta accountName y callback como entrada, el argumento callback es un contrato ubicado en la cuenta accountName . En la callback de callback 'e, llamamos al método del contrato recibido con el objeto, sus claves son los argumentos del método llamado.


Considere el método de lectura de tablas:


  readTable(data) { this.eos = this.scatter.eos(this.network, Eos, this.configEosInstance); return this.eos.getTableRows({ json: true, limit: 1, ...data, }); } 

Aquí para leer solo necesitamos una instancia de eos .


Para diseñar la interfaz, dejamos caer Materialise, Semantic y Ant, y preparamos estilos nosotros mismos. En las últimas horas del hackathon, apareció una idea para revivir la interfaz de usuario, agregar una visualización del proceso. Destacó las nuevas filas de la tabla durante dos segundos en verde y obtuvo un efecto genial a la cotizaciones de bolsa. La mejora aumentó significativamente el atractivo del proyecto y se convirtió en la etapa final de la construcción de la interfaz de usuario.


3. Asamblea


Tres horas antes del final del tiempo, teníamos una Raspberry Pi con el medidor de electricidad Mercury y un lector RFID conectado, así como una luz indicadora. Toda la electricidad de la mesa pasó por el Mercurio. Por cada 0.3125 Wh / h gastados, así como por cada "compra", Raspberry Pi envió transacciones a nuestra cadena de bloques, y el proveedor de servicios pudo administrar usuarios, sensores, facturación y ver estadísticas de consumo.



Durante otra hora, nos dedicamos tranquilamente a los controles y agregamos los toques finales. Dos horas antes del final de los tiempos, recibimos un producto completo con dos casos implementados, ilustrando completamente el concepto, ¡e incluso sin compromisos en los últimos minutos!


4. Demostración


Las demostraciones de proyectos (también conocidos como lanzamientos) consistieron en dos etapas. En la primera etapa, 69 equipos participantes se dividieron en cuatro grupos, cada uno de ellos fue alimentado por separado frente a dos jueces y sin espectadores. Los jueces otorgaron calificaciones (cuatro criterios de 5 puntos cada una) y, con base en estas calificaciones, los 10 mejores equipos fueron seleccionados para la segunda etapa. Estos equipos tuvieron la oportunidad de organizar un proyecto en un gran escenario frente a la audiencia y los ocho jueces.


Terminamos en el primer grupo, nuestros jueces fueron el CEO y presidente (me pregunto cómo difieren estas posiciones) de Everipedia. Se asignaron tres minutos para el rendimiento, se controlaron estrictamente por temporizador. Terminamos nuestro inconsistente, pero llamamos a impresionar el discurso 30 segundos antes de lo previsto. Los jueces preguntaron algo superficialmente y bastante pronto, y la manifestación terminó.


Nosotros, los ingenuos, nos sorprendió que no prestáramos atención a la capacidad de trabajo real del producto, y aún más al código del juez. Los problemas de implementación técnica no les interesaban ni en lo más mínimo. También podríamos mostrar las bombillas de Raspberry Pi y la imagen en el frente.


Había una sensación de que con la presentación del proyecto fracasamos, porque esperábamos impresionar con una solución real, un prototipo, y no solo una descripción colorida de un proyecto socialmente significativo y ambicioso. Todo se jugó como por notas: describimos el problema, el dolor, nuestra solución, mostramos cómo funciona y describimos los planes de desarrollo del proyecto. Conociendo de antemano los métodos de juzgar, hubiéramos hecho de manera muy diferente.


Los jueces de las cuatro transmisiones de la primera ronda redujeron sus puntajes e intercambiaron puntos de vista 15 minutos después del final de los lanzamientos. Después del anuncio de los ganadores comenzó. Una atmósfera nerviosa reinaba en la sala: cansados ​​después del maratón de 26 horas, la gente quería ganar, había muchos equipos fuertes y sabían que podían reclamar la victoria. Y lo sabíamos, y esperamos los resultados.


Para evitar que los espectadores se relajen, los resultados se anunciaron en tres partes. Los primeros cuatro finalistas, luego tres más, luego otros tres. Entre anuncios y al final - actuaciones. No entramos en el top 10 y no tuvimos la oportunidad de entrar en el gran escenario. Dos equipos de habla rusa llegaron a los diez primeros, uno de los cuales finalmente se convirtió en el tercero. Felicitaciones a los ganadores, se merecen sus premios.


5. Conclusión y planes


AngelHack . , . — , , . , , , — .


26 IoT- EOS. , .


— UI ( — -- Smartz ), . - , blockchain-ready , , — . :)



, , «», «» . . 5 . , 100 , . SensorPay !


:


Yuvasee (entrepreneur)
algs (hardware & backend developer)
therealal (architect, backend developer, devops)
bolbu (frontend developer)
quantum (blockchain & backend developer)

Source: https://habr.com/ru/post/es414803/


All Articles