TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block...

95
TRABAJO FINAL DE GRADO Block Lotto Autor: Jorge Fernández Molines Tutor: José Juan Hernández Cabrera

Transcript of TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block...

Page 1: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

TRABAJO FINAL DE GRADO

Block Lotto

Autor: Jorge Fernández Molines Tutor: José Juan Hernández Cabrera

Page 2: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

TFT04

Ver.12 21/05/18

D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración con la empresa/proyecto (indicar en su caso) S O L I C I T A que se inicie el procedimiento de defensa del mismo, para lo que se adjunta la documentación requerida. Asimismo, con respecto al registro de la propiedad intelectual/industrial del TFT, declara que:

[ ] Se ha iniciado o hay intención de iniciarlo (defensa no pública). [X] No está previsto.

Y para que así conste firma la presente.

Las Palmas de Gran Canaria, a 04 de enero de 2019.

El estudiante

Fdo.: ____________________________

DIRECTOR DE LA ESCUELA DE INGENIERÍA INFORMÁTICA

SOLICITUD DE DEFENSA DE TRABAJO DE FIN DE TÍTULO

A rellenar y firmar obligatoriamente por el/los tutor/es

En relación a la presente solicitud, se informa:

[X] Positivamente [ ] Negativamente

(la justificación en caso de informe

negativo deberá incluirse en el

TFT05)

Fdo.: ____________________________

Page 3: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

Contenido 1. Introducción .............................................................................................................................1

1.1 ¿Qué es Blockchain? ..........................................................................................................2

1.2 ¿Qué es Bitcoin? ................................................................................................................3

1.3 ¿Qué es Lightning Network? ..............................................................................................3

1.3.1 Transferencias con Lightning Network Daemon .........................................................4

2. Motivación y objetivos. ............................................................................................................6

3. Justificación de las competencias .............................................................................................7

4. Aportación socioeconómica .....................................................................................................9

5. Análisis .....................................................................................................................................9

5.1 Aplicaciones que hacen uso de Lightning Network ............................................................9

5.2 Descripción del proyecto .................................................................................................11

5.3 Problemas con Lightning Network ...................................................................................11

5.4 Características ..................................................................................................................13

5.5 Historias de usuario .........................................................................................................13

5.6 Riesgos .............................................................................................................................14

5.7 Licencias de software .......................................................................................................14

6 Diseño .....................................................................................................................................15

6.1 Diagrama de casos de uso ................................................................................................15

6.2 Diagramas de secuencia ...................................................................................................15

6.2.1 Crear cartera .............................................................................................................16

6.2.2 Borrar cartera ...........................................................................................................17

6.2.3 Desbloquear cartera .................................................................................................17

6.2.4 Restaurar cartera ......................................................................................................18

6.2.5 Obtener saldo de la cartera ......................................................................................18

6.2.6 Obtener saldo de los canales ....................................................................................19

6.2.7 Comprar boleto.........................................................................................................20

6.2.8 Ver notificaciones .....................................................................................................22

6.2.9 Marcar notificaciones ...............................................................................................22

6.2.10 Transferencias entre usuarios .................................................................................23

6.2.11 Listado de movimientos ..........................................................................................25

6.2.12 Listar todos los sorteos pendientes ........................................................................26

6.2.13 Cerrar canales para obtener su saldo .....................................................................27

6.2.14 Crear sorteo ............................................................................................................28

6.2.15 Eliminar sorteo .......................................................................................................28

Page 4: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

6.2.16 Comenzar sorteo ....................................................................................................28

6.2.17 Pagar premio ..........................................................................................................29

6.2.18 Celebrar un sorteo y generar otro del mismo tipo..................................................30

6.3 Diagrama de despliegue ...................................................................................................31

6.4 Diagrama de la base de datos ..........................................................................................32

7. Desarrollo ...............................................................................................................................32

7.1 Metodología .....................................................................................................................32

7.2 Planificación inicial y final ................................................................................................33

7.3 Configuración de los servidores .......................................................................................33

7.3.1 Configuración del servidor Urano .............................................................................34

7.3.2 Configuración del servidor Jupiter. ...........................................................................35

7.3.2.1 Instalación del servicio de base de datos Mysql ................................................35

7.3.2.2 Instalación de los nodos Bitcoin y Lightning Network. ......................................36

7.4. Problemas encontrados con Lightning Network .............................................................36

7.5 Explicación del código ......................................................................................................36

7.5.1 pom.xml ....................................................................................................................36

7.5.2 Main.java ..................................................................................................................39

7.5.3 Interfaz .....................................................................................................................40

7.5.4 Fichero de configuración ..........................................................................................40

7.5.5 BlockLottoService .....................................................................................................41

7.5.5.1 Crear cartera......................................................................................................41

7.5.5.2 Restaurar cartera ...............................................................................................42

7.5.5.3 Desbloquear cartera ..........................................................................................44

7.5.5.4 Consultar saldo de la cartera .............................................................................44

7.5.5.5 Comprar boletos ................................................................................................45

7.5.5.6 Consultar saldo en los canales abiertos. ............................................................56

7.5.5.7 Recuperar saldo de los canales abiertos. ...........................................................57

7.5.5.8 Historial de movimientos...................................................................................58

7.5.5.9 Realizar transferencias a otros usuarios ............................................................59

7.5.5.10 Consultar notificaciones ..................................................................................60

7.5.5.11 Marcar notificaciones como leídas ..................................................................61

7.5.5.12 Lista de todos los sorteos ................................................................................62

7.5.5.13 Lista de los sorteos pendientes de celebración. ..............................................62

7.5.5.14 Lista de los sorteos con participación ..............................................................63

7.5.5.15 Listar de los sorteos ya celebrados con participación......................................63

Page 5: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

7.5.6 Sistema de gestión de sorteos. .................................................................................64

7.5.6.1 Quartz Listener ..................................................................................................64

7.5.6.2 BlockDrawListener .............................................................................................66

7.5.6.3 StartDrawJob .....................................................................................................67

7.5.6.4 CloseMasterChannelJob ....................................................................................70

7.5.7 TDD ...........................................................................................................................70

7.5.7.1 ManageRaffleTest..............................................................................................71

7.5.7.2 MockLightningAccessorTest ..............................................................................73

8. Conclusiones y trabajos futuros .............................................................................................78

8.1 Resultado .........................................................................................................................78

8.2 Consecución de los objetivos ...........................................................................................79

8.3 Trabajos futuros ...............................................................................................................79

9. Herramientas utilizadas ..........................................................................................................80

9.1 Hardware .........................................................................................................................80

9.1.1 Ordenador portátil personal .....................................................................................80

9.1.2 Servidores .................................................................................................................80

9.2 Software ...........................................................................................................................80

9.2.1 Windows 10 Home ...................................................................................................80

9.2.2 IntelliJ IDEA Ultimate 2018.3 ....................................................................................80

9.2.3 Trello .........................................................................................................................80

9.2.4 SoapUI by SmartBear ................................................................................................80

9.2.5 Github .......................................................................................................................80

9.2.6 MySQL Workbench ...................................................................................................80

9.2.7 Github Desktop .........................................................................................................80

10. Referencias ...........................................................................................................................81

Anexo I: Manual de usuario del cliente ......................................................................................82

1. Creación de cartera ............................................................................................................82

2. Restauración de cartera .....................................................................................................83

3. Desbloqueo de cartera .......................................................................................................83

4. Consulta de saldo ...............................................................................................................84

5. Compra de boletos .............................................................................................................84

6. Consulta de saldo en los canales ........................................................................................84

7. Extraer fondos de los canales.............................................................................................85

8.Movimientos de pago .........................................................................................................85

9. Transferencias a otra cuenta ..............................................................................................85

Page 6: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

10. Ver notificaciones ............................................................................................................86

11. Marcar notificación como leída........................................................................................86

12. Listar todos los sorteos ....................................................................................................86

13. Listar los sorteos pendientes ...........................................................................................87

14. Listar los sorteos pendientes en los que participo ...........................................................87

15. Listar todos los sorteos en los que he participado ...........................................................88

Anexo II: Manual de usuario del administrador. ........................................................................88

1. Configuración de los sorteos ..............................................................................................88

1.1 Base de datos...............................................................................................................88

1.2 Quartz ..........................................................................................................................89

Page 7: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

1

1. Introducción Actualmente son muchas las noticias que aparecen en los medios de comunicación relacionadas

con el mundo de la blockchain. Es innegable que esta tecnología ha llegado para quedarse y

poco a poco se está volviendo más indispensable gracias a las ventajas que esta proporciona.

En este proyecto de fin de grado me centraré en el protocolo Lightning Network que presenta

sustanciosas mejoras con respecto a las características ofrecidas por la red Bitcoin por si sola.

Este novedoso protocolo aún se encuentra en fase de desarrollo por lo que no se recomienda

su uso en la red principal de bitcoin, debido a inconsistencias encontradas a la hora de ejecutar

diferentes funciones.

Se plantea el desarrollo de un producto software de lotería en el cual el usuario podrá participar

en sorteos comprando previamente boletos y en caso de ser el ganador recibir el premio. Los

pagos se realizan mediante una blockchain, concretamente bitcoin, haciendo a su vez uso del

protocolo lightning network, lo que posibilita los pagos instantáneos.

El objetivo de este proyecto es desarrollar el LottoService e integrarlo con el LottoWallet, que

se desarrollará como objetivo de otro TFT. Por tanto, este proyecto se realiza de forma conjunta

con otro estudiante, Cynthia J. Afonso García. El otro proyecto TFT constará de una interfaz

desarrollada en Android que se comunicará con el servicio a través del LottoService, para facilitar

de este modo al cliente, el uso de la aplicación.

Los clientes se comunicarán haciendo uso de una aplicación instalada en su teléfono móvil. Esta

establecerá una conexión con el servicio a través de un web service que también ha sido

desarrollado para este proyecto.

Ilustración 1 - Esquema BLockLotto

Este proyecto ha sido tutorizado por D. José Juan Hernández Cabrera, doctor titular en la ULPGC

del área de conocimiento de Ciencias de la Computación e Inteligencia Artificial.

Antes de continuar conviene aclarar algunos conceptos como son Blockchain, Bitcoin y Lightning

Network.

Page 8: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

2

1.1 ¿Qué es Blockchain? Es una tecnología la cual nos permite sin necesidad de intermediarios, cualquier tipo de

transacción entre dos o más personas de una manera fiable y segura. Para entendernos diremos

que la blockchain es como un libro de contabilidad en el que se irán añadiendo apuntes de los

distintos movimientos que se vayan produciendo entre las distintas carteras digitales, agrupados

en lo que llamamos bloques.

Las carteras digitales son interfaces con las que el cliente puede interactuar con la red

blockchain. Con ellas los usuarios pueden realizar transacciones, ver su saldo y administrar su

identidad digital. Estas carteras digitales poseen identificadores que las hacen únicas.

Para que todo el sistema funcione, es necesario que una cantidad indeterminada de

computadoras resuelvan un problema matemático del protocolo de consenso, para así autorizar

la adición de los bloques de transacciones que generan las carteras digitales.

En este protocolo de consenso, se recompensa a los nodos a cambio de crear un bloque. Pueden

existir varias cadenas de consenso, pero solamente la cadena más larga, determinará si la

transacción queda validada o no. Al crear un bloque, el nodo, incluye una transacción de

creación de monedas en ese mismo bloque. Este nodo puede escoger la dirección a la que serán

enviadas esas monedas. Para poder crear el bloque, el nodo debe resolver un problema hash.

La dificultad de resolución de este problema varía según la cantidad total de procesamiento que

se encuentra en esa red blockchain en un momento dado. De esta manera blockchain se protege

de posibles ataques a la cadena de bloques.

Por otro lado, nos encontramos los nodos, que se encargan tanto de hacer cumplir las normas

como de guardar una copia exacta de la red blockchain. Dentro de este apartado debo de hacer

mención de la descentralización. Las blockchains pueden ser o no descentralizadas. Como

ejemplo de una red descentralizada tenemos la criptomoneda bitcoin basada en blockchain. En

contra tenemos, por ejemplo, las redes internas de los bancos que trabajan con sus propias

redes blockchain. Una red descentralizada impide que el poder para controlar y aprobar o

desaprobar transacciones, recaiga en una única parte. Esto es, el poder se encuentra distribuido

entre muchas partes que deben de llegar a un acuerdo para poder realizar cambios en las reglas

que legislan el funcionamiento de la blockchain. De esta manera en una red descentralizada, un

nodo no puede aceptar o desestimar transacciones unilateralmente.

Con todo esto, tenemos que la tecnología blockchain nos garantiza que todos los registros de

transacciones sean legítimos e inmutables. Cada dato o transacción posee una huella digital

única, esto es, no podemos repetir ni modificar lo anteriormente incluido en la blockchain.

Son varios los usos que se le está dando a las cadenas de bloques. Algunos de los más

extendidos: Criptomonedas, registro de documentos, operaciones comerciales, trazabilidad de

suministros y contratos inteligentes.

Referencias: [1]

Page 9: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

3

1.2 ¿Qué es Bitcoin? Bitcoin es una moneda virtual basada en la tecnología blockchain. Fue la primera criptomoneda

creada con dicha tecnología. Su creador, anónimo, es conocido por el pseudónimo de “Satoshi

Nakamoto”.

Posee las siguientes características:

• Permite realizar micropagos: Un bitcoin puede dividirse en un número determinado de

satoshis, concretamente en la proporción un bitcoin es igual a cien millones de satoshis. Esto

permite que podamos realizar pagos por una cantidad mínima de 546 satoshis o lo que es

lo mismo que 0,00000546 Bitcoins. A la unidad Satoshi se le llama así en honor al creador

de la moneda.

• Posibilidad de realizar grandes transacciones rápidamente y sin complicaciones.

• Protección contra la inflación: El número total de bitcoins que podrá crear el sistema es de

21 millones. Al no existir una generación infinita de monedas, no se produce la inflación o

pérdida de valor de la moneda.

• Descentralizado: No puede ser controlado por un ente ya que se necesita el acuerdo de una

gran mayoría de nodos para cambiar las reglas de uso de esta moneda.

• Permite las transacciones internacionales.

• Es seguro.

• Fungible: Se puede intercambiar por bienes de un valor similar.

Algunos de los problemas encontrados en Bitcoin:

• Escalabilidad: Existe una limitación en el número de transacciones que pueden ser

procesadas en un intervalo específico de tiempo. Esto sucede a causa de un aumento

considerable de usuarios y con ello transacciones.

• Programación limitada: Al tratarse de una criptomoneda de primera generación, no está del

todo preparada para la creación de smart contracts.

• Lentitud a la hora de realizar las transacciones: De media se debe esperar unos 10 minutos

hasta que la transacción se confirme. Esto impide que podamos usar bitcoin para realizar

micro transacciones en nuestras compras del día a día.

• Comisiones elevadas por transacción.

Referencias: [2] [3] [4] [5] [6]

1.3 ¿Qué es Lightning Network? Es un protocolo creado por Joseph Poon y Thaddeus Dryja, que se ejecuta sobre la red bitcoin y

da solución a algunos problemas anteriormente mencionados.

Principales características:

• Permite los pagos instantáneos. Ya no es necesaria la validación de cada transacción. Con

ello nos ahorraremos los tiempos de validación que hacían impracticable las micro

transacciones en las compras del día a día. Por ejemplo, si vamos a una cafetería y queremos

comprar un café usando el protocolo lightning network, veremos como la transacción

finaliza instantáneamente, obteniendo el café de forma también instantánea. Al contrario,

si esta transacción la hiciéramos pagando únicamente con la red bitcoin, tardaríamos en

Page 10: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

4

obtener la confirmación entre diez minutos y una hora, dependiendo de lo congestionada

que estuviera la red. De este modo el dueño de la tienda, no nos daría el producto hasta que

obtuviera la confirmación.

• Mejora enormemente la escalabilidad de la red, gracias a que permite un aumento

considerable del número de transacciones efectuadas por segundo.

• Las comisiones en la red Lightning Network son más bajas. Esto permite realizar micro

transacciones y no tener que pagar grandes cantidades de comisiones. En cambio, en la red

bitcoin, dependiendo de la cantidad de dinero a transferir, podría darse la circunstancia de

que las comisiones fueran iguales a la cantidad de dinero que se quiere enviar.

Referencias: [8]

1.3.1 Transferencias con Lightning Network Daemon

En este apartado se explicará cómo funcionan las transferencias en Lightning Network.

En primer lugar, es necesaria la creación de una cartera Bitcoin sobre un nodo Lightning para

poder realizar transferencias instantáneas. De hecho, ambas carteras deben de ser creadas

sobre un nodo Lightning. Se debe establecer una conexión entre ambas carteras, a esto Lightning

lo llama peer. Una vez las carteras ya están conectadas, se puede abrir un canal para comenzar

a realizar transferencias. Cuando se abre el canal, la cartera que lo abre puede añadir fondos a

ambas partes. Lightning Network Daemon no permite por el momento que ambas carteras

inserten fondos en un mismo canal, como tampoco permite insertar fondos después de que el

canal haya sido creado. Para la creación del canal es necesario el minado de 6 bloques. En ese

momento se registra en la blockchain. Teniendo en cuenta que el minado de un bloque en la red

Bitcoin tarda un promedio de 10 minutos, tenemos que esperar una hora por la creación del

canal. Sin embargo, una vez creado el canal, se podrán realizar tantas transferencias

instantáneas como se quieran, siempre y cuando se dispongan de suficientes fondos dentro del

canal. Hay que señalar que, en la creación de un canal, se cobra una comisión de 9050 satoshis.

En este ejemplo vemos como Mary y Adrián son dos nodos de Lightning Network.

Ilustración 2 - Diagrama de pago directo 1

Mary ha abierto un canal, y ha metido 3 Bitcoins dentro de este. Vamos a obviar las comisiones

de 9050 satoshis para simplificar el ejemplo.

Page 11: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

5

Ilustración 3 - Diagrama de pago directo 2

Mary y Adrián podrán realizar tantas transacciones como quieran de manera instantánea hasta

el punto en el que el canal queda de esta manera.

Ilustración 4 - Diagrama de pago directo 3

En cualquier momento cualquier de los dos nodos puede elegir cerrar el canal para recuperar el

saldo en su parte del canal. Para efectuar el cierre del canal, es necesario el minado de un

bloque. Por lo que el cerrado de canales tampoco es un proceso instantáneo, tardaría en

cerrarse unos 10 minutos. Es en este momento cuando se registra la transferencia en la

Blockchain.

Situación una vez cerrado el canal.

Ilustración 5 - Diagrama de pago directo 4

También es posible realizar pagos a través de canales ajenos al nuestro. Partimos de la base que

hay unos nodos ya creados y que tienen canales abiertos entre ellos.

Page 12: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

6

Ilustración 6 - Diagrama de pago con multi-hop 1

Adrián quiere pagarle 3 Bitcoins a Mary, pero no tiene una conexión directa con ella. Esto no

tiene importancia ya que Jorge puede hacer de intermediario. No se necesita su aprobación para

utilizarlo de intermediario ya que Jorge antes y después de la transferencia, seguirá teniendo la

misma cantidad total de fondos en sus canales.

Ilustración 7 - Diagrama de pago con multi-hop 2

Vemos como Adrián ha perdido 3 Bitcoins, Jorge se ha quedado con los 6 que tenía en un

principio, pero distribuidos de manera diferente y Mary ha ganado 3 hasta tener 5 Bitcoins.

A este procedimiento de realizar pagos a través de un tercero se le llama multi-hop. En este

ejemplo solo ha habido un intermediario, pero podrían haber sido muchos más.

Referencias: [10] [11]

2. Motivación y objetivos. Como se ha comentado anteriormente, blockchain es una tecnología en auge que no he tenido

oportunidad de estudiar en el grado. Es por ello por lo que me parece interesante profundizar

más en esta materia, teniendo en cuenta la cantidad de campos donde se podría aplicar esta

tecnología.

Podemos encontrar aplicaciones en distintos sectores:

• Sanidad:

o Se pueden reducir los fraudes en pagos en el sector sanitario.

o Controlar la disponibilidad de historiales médicos y así mantener la privacidad.

• Sector financiero:

o Transferencias más rápidas que con las monedas del sistema tradicional.

o Estas transferencias se pueden realizar a cualquier hora del día.

• Servicios legales:

o En los contratos inteligentes, no es necesario el intermediario ya que es el mismo

contrato el que vigila que la ley de este se cumpla.

• Entidades gubernamentales:

Page 13: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

7

o El suministro de información entre el ciudadano y la entidad ocurre en tiempo

real.

o Se reduce la corrupción y se aumenta la transparencia.

Por otro lado, la reciente aparición del protocolo Lightning Network, como anteriormente

comentamos, corrige los problemas de escalabilidad e inmediatez en los pagos con Bitcoin. Me

parece muy interesante su estudio para entender mejor su funcionamiento y quien sabe, quizás

aplicar lo que pueda aprender en este proyecto en un futuro.

Los objetivos del presente proyecto son:

• Conocer mejor la blockchain, bitcoin y Lightning Network a través de un caso práctico.

• Poner en práctica lo aprendido en el grado. Esta es la primera oportunidad que tengo de

enfrentarme a un proyecto tras haber estudiado el Grado en Ingeniería Informática. Me

gustaría poner en práctica todo lo aprendido para de esta manera mejorar y poder

convertirme en un buen profesional.

Referencias: [18]

3. Justificación de las competencias Se han justificado las siguientes competencias.

CII01 - Capacidad para diseñar, desarrollar, seleccionar y evaluar aplicaciones y sistemas

informáticos, asegurando su fiabilidad, seguridad y calidad, conforme a principios éticos y a la

legislación y normativa vigente.

Competencia justificada ya que este proyecto se ha llevado a cabo pasando por fases de análisis,

diseño, implementación y verificación a través de TDD para verificar su correcto funcionamiento.

CII02 - Capacidad para planificar, concebir, desplegar y dirigir proyectos, servicios y sistemas

informáticos en todos los ámbitos, liderando su puesta en marcha y su mejora continua y

valorando su impacto económico y social.

Competencia justificada ya que, para desarrollar este proyecto, se ha tenido que planificar el

mismo para que la integración con la parte del LottoService sea una realidad. Se han establecido

unas condiciones entre los dos proyectos para no encontrarnos problemas cuando el

LottoWallet haga uso del LottoService.

CII03 - Capacidad para comprender la importancia de la negociación, los hábitos de trabajo

efectivos, el liderazgo y las habilidades de comunicación en todos los entornos de desarrollo

de software

Competencia justificada ya que, para poder desarrollar este proyecto, he tenido que ponerme

de acuerdo con la desarrolladora de la otra parte del proyecto, Cynthia J. Afonso García, en los

aspectos que atañen a ambas.

CII08 - Capacidad para analizar, diseñar, construir y mantener aplicaciones de forma robusta,

segura y eficiente, eligiendo el paradigma y los lenguajes de programación más adecuados

Competencia justificada ya que se ha elegido el lenguaje de programación Java, el cual es

adecuado para el desarrollo del proyecto. Por otro lado, se ha desarrollado el proyecto desde

cero, con sus fases de análisis y diseño.

Page 14: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

8

CII011 - Conocimiento y aplicación de las características, funcionalidades y estructura de los

Sistemas Distribuidos, las Redes de Computadores e Internet y diseñar e implementar

aplicaciones basadas en ellas.

Competencia justificada ya que el LottoWallet se comunica con este proyecto, el LottoService a

través de internet para hacer peticiones al web service.

CII013 - Conocimiento y aplicación de las herramientas necesarias para el almacenamiento,

procesamiento y acceso a los Sistemas de información, incluidos los basados en web

Competencia justificada ya que en el proyecto se hace uso de una base de datos Mysql para el

correcto almacenamiento de la información.

CII016 - Conocimiento y aplicación de los principios, metodologías y ciclos de vida de la

ingeniería de software.

Competencia justificada ya que con el desarrollo de este proyecto se hace uso de la metodología

iterativa. Por otro lado, en el apartado de diseño se hace uso de diagramas que facilitan el diseño

del producto. Lo anteriormente comentado, es todo propio de la ingeniería de software.

IS01 - Capacidad para desarrollar, mantener y evaluar servicios y sistemas software que

satisfagan todos los requisitos del usuario y se comporten de forma fiable y eficiente, sean

asequibles de desarrollar y mantener y cumplan normas de calidad, aplicando las teorías,

principios, métodos y prácticas de la ingeniería del software.

Competencia justificada ya que este proyecto trata sobre el desarrollo de un servicio web, el

cual cumple todos los requisitos del usuario. Se pueden ver las historias de usuario en el punto

de historias de usuario.

IS02 - Capacidad para valorar las necesidades del cliente y especificar los requisitos software

para satisfacer estas necesidades, reconciliando objetivos en conflicto mediante la búsqueda

de compromisos aceptables dentro de las limitaciones derivadas del coste, del tiempo, de la

existencia de sistemas ya desarrollados y de las propias organizaciones.

Competencia justificada ya que, para el desarrollo de este proyecto, se ha tenido que seguir un

proceso de análisis, donde se puede ver las aplicaciones que hacen uso de Lightning Network y

como se comentó en el punto anterior las historias de usuario.

IS03 - Capacidad de dar solución a problemas de integración en función de las estrategias,

estándares y tecnologías disponibles.

Competencia justificada ya que para la creación del web service, primero se especificó junto al

proyecto de la LottoWallet cuales serían los parámetros que devolverían los distintos métodos

del servicio web.

IS04 - Capacidad de identificar y analizar problemas y diseñar, desarrollar, implementar,

verificar y documentar soluciones software sobre la base de un conocimiento adecuado de las

teorías, modelos y técnicas actuales.

Competencia justificada ya que como se explicó en el apartado de problemas con Lightning

Network, se tuvo que buscar una solución a un problema con una tecnología demasiado

temprana.

Page 15: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

9

IS05 - Capacidad de identificar, evaluar y gestionar los riesgos potenciales asociados que

pudieran presentarse.

Competencia justificada con el apartado riesgos.

IS06 - Capacidad para diseñar soluciones apropiadas en uno o más dominios de aplicación

utilizando métodos de la ingeniería del software que integren aspectos éticos, sociales, legales

y económicos.

Competencia justificada con todo lo anteriormente dicho.

4. Aportación socioeconómica Este proyecto simula el uso del protocolo Lightning en un pequeño caso de uso como es un

sorteo. Pero Lightning está directamente relacionado con Bitcoin y a su vez Bitcoin con la

Blockchain. Es innegable que hoy en día estamos viviendo una gran revolución con todo lo

relacionado con las criptomonedas, además de las diferentes aplicaciones que se les está dando

alrededor de todo el mundo a la tecnología Blockchain.

Bitcoin fue la primera moneda generada por medio de la tecnología Blockchain y hoy en día

sigue siendo la moneda referencia. Se le achacan algunos problemas como son la lentitud a la

hora de verificar los pagos y por otro lado el bajo número de transacciones que se pueden

realizar por segundo. Lightning Network llega para dar solución a estos dos problemas. Dota a

Bitcoin de inmediatez en los pagos una vez se haya abierto un canal y por otro lado permite un

altísimo número de transacciones por segundo.

En resumen, Lightning tiene un alto nivel socio económico ya que potenciará el uso de Bitcoin

como moneda para realizar micropagos en las compras del día a día.

Referencias: [8]

5. Análisis

5.1 Aplicaciones que hacen uso de Lightning Network Actualmente están apareciendo bastantes desarrollos que hacen uso del protocolo lightning

network. Podemos destacar las tres siguientes implementaciones:

• LND: Lightning Network Daemon.

• Eclair: Implementación realizada en Scala.

• C-lightning: Implementación en C++.

A continuación, se mostrarán algunos ejemplos:

• Lightning Desktop App por Lightning Labs: Se trata de una cartera de bitcoin compatible con

Lightning Network. Aplicación de escritorio multiplataforma desarrollada con LND. [19]

Page 16: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

10

Ilustración 8 - Lightning Desktop App

• Y’alls: Plataforma en la que podemos leer y escribir artículos. Nos permite leer artículos

después de haber pagado una cierta cantidad. Este pago se puede realizar usando el

protocolo Lightning Network. [20]

Ilustración 9 - Y'alls

Page 17: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

11

• lnd.fun: Panel para web masters que permite controlar sus nodos Lightning Network. [21]

Ilustración 10 - lnd.fund

5.2 Descripción del proyecto Como se ha comentado anteriormente, en este proyecto se desarrollará un servicio web el cual

permitirá al cliente crearse una cartera bitcoin compatible con Lightning Network y poder así,

realizar compras de boletos instantáneamente para participar en un sorteo determinado.

También el cliente podrá realizar transferencias a otras carteras Lightning haciendo uso de

canales ajenos al emisor si existiera una ruta válida.

El sistema celebrará el sorteo en el día y hora especificados y entregará el premio al ganador de

este. Los sorteos se bloquearán 15 minutos antes de su celebración para no permitir la compra

de boletos. De igual modo se bloquearán si no quedaran boletos disponibles. Por otro lado, si a

la hora de celebrarse un sorteo, ningún usuario hubiera comprado boletos para este, el sorteo

será cancelado. Acto seguido de celebrar o cancelar un sorteo, el sistema creará un sorteo del

mismo tipo para dentro de una semana a la misma hora.

El sistema ganará aproximadamente un 20% de todos los fondos destinados a comprar boletos

en cada sorteo, por lo que el 80% restante irá destinado al premio. También el sistema

recolectará todos los fondos de sus canales Lightning abiertos, el día uno de cada mes. De esta

manera el sistema recupera sus ganancias.

Como se explicará en el siguiente punto, se ha pasado de realizar el proyecto usando el

protocolo Lightning Network a una simulación de este con ayuda de una base de datos.

5.3 Problemas con Lightning Network He encontrado diversos problemas en el transcurso del desarrollo de este proyecto ya que

Lightning Network es un protocolo todavía en construcción y por ello inestable en muchos casos.

El proyecto usado para el desarrollo es Lightning Network Daemon, este es el primer daemon

de Lightning, escrito en Go y desarrollado por Lightning Labs. Para poder desarrollar en Java es

necesario escribir un proyecto en java que sea capaz de comunicarse con LND a través de gRPC.

Remote Procedure Calls o lo que es lo mismo gRPC, es un sistema creado por Google en código

abierto y capaz de realizar llamadas de procedimientos remotos. Es capaz de generar enlaces de

cliente y servidor multiplataforma en varios idiomas. Seguí la guía que se detalla en esta página

del proyecto LND [16], pero no conseguí que funcionara. Al ver que me daba problemas me puse

en contacto con los desarrolladores de LND, a través de su canal oficial en Slack [13]. Los

Page 18: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

12

desarrolladores de Lightning Labs, me dijeron que estaba dando problemas puntuales en la

generación con java. Según me explicaron el problema estaba relacionado con la configuración

de los ficheros proto y que lo solucionarían en la siguiente versión. Después de esto descarté

usar LND por que no podía esperar que sacaran una nueva versión y opté por buscar alguna otra

solución.

Preguntando en Slack me dijeron que podría probar con la librería Lightningj [12]. Esta librería

facilita el uso de Lightning Network Daemon en desarrollos con el lenguaje Java. Realicé unas

pruebas para ver si podía crear carteras tanto de manera asíncrona como síncrona. Conseguí

crearlas en los dos modos, pero luego en una segunda llamada al procedimiento de creación,

para crear una segunda cartera, este fallaba. Al no conseguir solucionar el problema, me puse

en contacto con el desarrollador de esa librería, no pudiendo tampoco encontrar la solución.

Continué preguntando en Slack sobre estos errores y no conseguí ninguna respuesta que

pudiera ayudarme.

Casi todos los desarrollos que se realizan sobre Lightning Network están desarrollados en

JavaScript o Python. A causa de esto, en la red se puede encontrar información de errores

puntuales relacionados con Lightning Network Daemon para esos lenguajes, pero no para Java.

No he conseguido encontrar un proyecto realizado en Java que pudiera ayudarme de algún

modo. Por otro lado, la documentación de LND está únicamente redactada para JavaScript y

Python.

Leyendo los comentarios de otros usuarios en Slack y viendo los problemas publicados por

usuarios en el Github de LND, pude constatar que este proyecto, aun siendo uno de los más

avanzados relacionados con Lightning Network, le fatal bastante maduración, tanto en

funcionalidades como en lo que a estabilidad se refiere. En Slack son muchos los usuarios que

reportan errores como por ejemplo que existen ocasiones en las que los canales cerrados no

devuelven los fondos a sus respectivos dueños, quedándose en el sistema canales zombis con

enormes cantidades de bitcoins. Todos estos desarrollos usan la simnet o testnet para realizar

las pruebas. LND no recomienda el uso del Daemon en la mainnet por los muchos errores que

ocurren actualmente. Hay recalcar que Lightning Network Daemon está ahora mismo en su

versión 0.5.1 Beta.

Habiéndole dedicado bastante tiempo en intentar solucionar todos estos problemas y

encontrarme en un punto muerto debido a la escasa documentación que existe para el

desarrollo de Lightning Network Daemon en Java, hablé con mi tutor del TFG explicándole mi

problema. Me dijo que a partir de ese momento trabajara en una solución simulada de cómo

funciona Lightning Network Daemon con ayuda de una base de datos.

Page 19: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

13

5.4 Características Las características de este proyecto son:

• Web Service.

• Servicio de loterías.

• Simulación del protocolo Lightning Network.

• Permite las transferencias entre carteras Lightning.

• Desarrollo en Java.

5.5 Historias de usuario A continuación, expondré las historias de usuario del proyecto.

• Como usuario quiero crear una cartera para poder operar con ella.

• Como usuario quiero eliminar mi cartera para borrarla del sistema.

• Como usuario quiero restaurar mi cartera para recuperar mis fondos.

• Como usuario quiero desbloquear mi cartera para poder operar con ella.

• Como usuario quiero realizar transferencias a otras carteras para transferir dinero a otra

cuenta.

• Como usuario quiero comprar boletos para poder participar en sorteos.

• Como usuario quiero cerrar todos mis canales para recuperar mis fondos.

• Como usuario quiero listar todos los sorteos en los que he participado para ver mi historial

de sorteos.

• Como usuario quiero listar todos los sorteos pendientes para poder comprar boletos de esos

sorteos.

• Como usuario quiero listar todos los sorteos ya celebrados para ver el historial de sorteos.

• Como usuario quiero listar los sorteos en los que esté participando para ver la información

de dicho sorteo.

• Como usuario quiero ver las notificaciones para saber si he sido el ganador de algún sorteo.

• Como usuario quiero marcar como leída una notificación para que aparezca con otro diseño.

• Como usuario quiero poder comprobar mi saldo para saber cuánto dinero tengo en mi

cartera.

• Como usuario quiero saber cuánto dinero hay en mis canales para poder decidir si

recuperarlo.

• Como sistema quiero crear sorteos para añadirlos al listado de sorteos pendientes.

• Como sistema quiero cancelar sorteos para eliminarlos del listado de pendientes.

• Como sistema quiero celebrar sorteos para conseguir un ganador.

• Como sistema quiero pagar premios para premiar al ganador de un sorteo.

• Como sistema quiero cerrar todos mis canales para recuperar el dinero que hay en ellos.

Page 20: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

14

5.6 Riesgos Se han detectado los posibles siguientes riesgos:

• Desconocimiento del desarrollo con Blockchain, Lightning Network y Bitcoin: Al no tener

experiencia en desarrollo con estas tecnologías y utilizarlas por primera vez en el desarrollo

de este proyecto, se puede generar un retraso considerable. Riesgo de tipo tecnológico

(Técnico).

o Plan de contingencia: Realizar cursos relacionados con estas nuevas tecnologías.

• Cambio en la legislación: si se produjera un cambio en la legislación y se prohibiera el

Bitcoin, no podría seguir ofreciendo el servicio. Riesgo de tipo Regulatorio (Externo)

o Plan de contingencia: Se debería contratar un abogado que fuera un experto en lo

referente a lo legal en este tipo de tecnologías.

• Calidad del producto final: Al no tener experiencia en el desarrollo de proyectos orientados

a servicios web, podría suceder que la calidad de este no fuera todo lo buena como sería

deseable. Riesgo relacionado con la calidad (Técnico)

o Plan de contingencia: Asesoramiento de un profesional del sector que muestre el

camino a seguir para una correcta ejecución del desarrollo.

5.7 Licencias de software Para la realización del proyecto he utilizado los siguientes programas con licencia.

• IntelliJ IDEA Ultimate 2018.3: Licencia a mi nombre otorgada para propósitos educacionales.

• Office 365: Licencia otorgada a través de la ULPGC.

• Windows 10: Licencia otorgada a través de la ULPGC.

Los demás programas utilizados son versiones de prueba o software gratuito.

Page 21: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

15

6 Diseño

6.1 Diagrama de casos de uso Acorde a las historias de usuario ya comentadas en el punto 3.5, tenemos el siguiente diagrama

de casos de uso.

Ilustración 11 - Diagrama de casos de uso

6.2 Diagramas de secuencia En este punto mostraré cuales son las interacciones entre objetos en el sistema para cada una

de las funcionalidades del proyecto.

Page 22: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

16

6.2.1 Crear cartera

Ilustración 12 - Diagrama de secuencia - Crear cartera

Page 23: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

17

6.2.2 Borrar cartera

Ilustración 13 - Diagrama de secuencia - Borrar cartera

6.2.3 Desbloquear cartera

Ilustración 14 - Diagrama de secuencia - Desbloquear cartera

Page 24: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

18

6.2.4 Restaurar cartera

Ilustración 15 - Diagrama de secuencia - Restaurar cartera

6.2.5 Obtener saldo de la cartera

Ilustración 16 - Diagrama de secuencia - Obtener saldo de cartera

Page 25: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

19

6.2.6 Obtener saldo de los canales

Ilustración 17 - Diagrama de secuencia - Obtener saldo de los canales

Page 26: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

20

6.2.7 Comprar boleto

Ilustración 18 - Diagrama de secuencia - Comprar boleto 1

Page 27: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

21

Ilustración 19 - Diagrama de secuencia - Comprar boleto 2

Page 28: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

22

6.2.8 Ver notificaciones

Ilustración 20 - Diagrama de secuencia - Ver notificaciones

6.2.9 Marcar notificaciones

Ilustración 21 - Diagrama de secuencia - Marcar notificaciones

Page 29: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

23

6.2.10 Transferencias entre usuarios

Ilustración 22 - Diagrama de secuencia - Transferencia entre usuarios 1

Page 30: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

24

Ilustración 23 - Diagrama de secuencia - Transferencia entre usuarios 2

Page 31: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

25

6.2.11 Listado de movimientos

Ilustración 24 - Diagrama de secuencia - Listado de movimientos

Page 32: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

26

6.2.12 Listar todos los sorteos pendientes

Ilustración 25 – Diagrama de secuencia - Listar todos los sorteos pendientes

Page 33: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

27

6.2.13 Cerrar canales para obtener su saldo

Ilustración 26 - Diagrama de secuencia - Cerrar canales para obtener su saldo

Page 34: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

28

6.2.14 Crear sorteo

Ilustración 27 - Diagrama de secuencia - Crear sorteo

6.2.15 Eliminar sorteo

Ilustración 28 - Diagrama de secuencia - Eliminar sorteo

6.2.16 Comenzar sorteo

Ilustración 29 - Diagrama de secuencia - Comenzar sorteo

Page 35: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

29

6.2.17 Pagar premio

Ilustración 30 - Diagrama de secuencia - Pagar premio

Page 36: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

30

6.2.18 Celebrar un sorteo y generar otro del mismo tipo

Ilustración 31 - Diagrama de secuencia - Celebrar un sorteo y generar otro del mismo tipo

Page 37: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

31

6.3 Diagrama de despliegue Como se puede ver en el siguiente diagrama el sistema se compone de dos servidores. Ambos

tendrán instalado el sistema operativo Ubuntu 18.10 x64 y tendrán 1GB de RAM. Urano tendrá

instalado el Apache Tomcat/ 9.0.12 y Jupiter la base de datos Mysql junto con el nodo Bitcoin y

el Lightning Network Daemon. La conexión desde el web service hasta los dispositivos móviles

se hará a través del protocolo http

Ilustración 32 - Diagrama de despliegue

Page 38: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

32

6.4 Diagrama de la base de datos Como se puede ver en el diagrama se ha intentado evitar la redundancia de datos en las tablas.

Se han establecido diferentes claves foráneas para que, a la hora de eliminar carteras o sorteos,

se eliminen en cascada las tuplas relacionadas con esos datos.

Ilustración 33 - Diagrama de la base de datos

7. Desarrollo

7.1 Metodología Para el desarrollo del proyecto se ha hecho uso de metodologías ágiles. Estas metodologías son

técnicas que agilizan el desarrollo de software, favoreciendo a la toma de decisiones, donde los

requisitos y soluciones evolucionan con el tiempo según las necesidades.

La metodología elegida para el desarrollo del proyecto ha sido la iterativa. A continuación, se

muestran cuáles han sido las iteraciones realizadas en este proyecto:

1. Creación, eliminación y desbloqueo de una cartera.

2. Restauración de una cartera.

3. Creación de sorteos.

4. Compra de boletos

Page 39: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

33

5. Celebración de sorteos y pago de premios.

6. Realización de transferencias.

7. Listar sorteos

8. Comprobar saldo de la cartera y de los canales. Además de cerrar todos los canales para

recuperar el saldo.

9. Programación semanal relacionada con el bloqueo, celebración y creación de sorteos.

Además de la retirada de fondos de los canales de la cartera maestra para recuperar

fondos.

7.2 Planificación inicial y final En el siguiente cuadro podemos ver cuál fue la planificación inicial del proyecto.

Ilustración 34 - Tabla de planificación

El “estudio previo / Análisis” me llevó bastante más de lo esperado ya que me encontré con los

problemas anteriormente mencionados, relacionados con Lightning Network. De 125 horas

estimadas, superé las 200 horas. Los demás apartados se han acercado bastante a sus

estimaciones. En general se puede afirmar que no acerté con la estimación ya que lo problemas

encontrados en la primera fase, hicieron que superara por mucho el tiempo establecido.

7.3 Configuración de los servidores Para el desarrollo de este proyecto he contado con dos servidores contratados a la empresa

Digitalocean. Estos servidores están hospedados en Londres. Tienen como sistema operativo el

Linux 18.10 x64 y 1GB de RAM. Opté por contratar con esta compañía ya que gracias al student

pack de Github, regalan 50$ para gastarlos en sus servicios. Además, anteriormente les he dado

uso en otros proyectos y me han respondido bastante bien.

Page 40: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

34

7.3.1 Configuración del servidor Urano

Este es el servidor que dará el servicio de servidor web. Para ello instalaremos en el mismo el

Apache Tomcat 9.0.12. Los pasos seguir para su instalación son los siguientes.

Comandos:

Instalar Java sudo apt update sudo apt install default-jdk

Crear el usuario Tomcat sudo groupadd tomcat sudo useradd -s /bin/false -g tomcat -d /opt/tomcat tomcat

Instalar Tomcat cd /tmp curl -O <dirección del paquete apache-tomcat-9.0.12.tar.gz> sudo mkdir /opt/tomcat sudo tar xzvf apache-tomcat-9*tar.gz -C /opt/tomcat --strip-components=1

Actualizar los permisos cd /opt/tomcat sudo chgrp -R tomcat /opt/tomcat sudo chmod -R g+r conf sudo chmod g+x conf sudo chown -R tomcat webapps/ work/ temp/ logs/

Editamos el fichero de configuración de Tomcat para ejecutarlo como un servicio. sudo nano /etc/systemd/system/tomcat.service

Pegamos el contenido y guardamos. [Unit] Description=Apache Tomcat Web Application Container After=network.target [Service] Type=forking Environment=JAVA_HOME=/usr/lib/jvm/java-1.11.0-openjdk-amd64 Environment=CATALINA_PID=/opt/tomcat/temp/tomcat.pid Environment=CATALINA_HOME=/opt/tomcat Environment=CATALINA_BASE=/opt/tomcat Environment='CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC' Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom' ExecStart=/opt/tomcat/bin/startup.sh ExecStop=/opt/tomcat/bin/shutdown.sh User=tomcat Group=tomcat UMask=0007 RestartSec=10 Restart=always [Install] WantedBy=multi-user.target sudo systemctl daemon-reload sudo systemctl start tomcat sudo systemctl status tomcat

Page 41: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

35

Ahora podemos comprobar si el servicio está correctamente instalado. http://server_domain_or_IP:8080

Configuramos el servicio para que se inicie con cada inicio del servidor. sudo systemctl enable tomcat

Configuración de la interfaz web para controlar el servidor Tomcat. Editamos el admin y la contraseña sudo nano /opt/tomcat/conf/tomcat-users.xml

<tomcat-users . . .> <user username="admin" password="password" roles="manager-gui,admin-gui"/> </tomcat-users>

Para poder acceder desde el exterior a la interfaz es necesario desactivar una

restricción que trae por defecto Tomcat en las últimas versiones. En los dos siguientes archivos comentamos la línea que restringe la conexión desde el

exterior del servidor. sudo nano /opt/tomcat/webapps/manager/META-INF/context.xml sudo nano /opt/tomcat/webapps/host-manager/META-INF/context.xml <Context antiResourceLocking="false" privileged="true" > <!--<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />--> </Context>

Ya tenemos instalado el servicio Tomcat en nuestro servidor, ahora lo único que

tenemos que hacer es acceder al mismo e incluir el fichero .war generado desde Intellij para que el servicio esté disponible para ser usado sin ningún problema.

7.3.2 Configuración del servidor Jupiter. Este servidor es el encargado de alojar la base de datos Mysql y por otro lado también es el

servidor donde se instalaron los nodos de Bitcoin y Lightning Network.

7.3.2.1 Instalación del servicio de base de datos Mysql

En la instalación de Mysql tuve que seguir los siguientes pasos. sudo apt update

sudo apt install mysql-server

sudo mysql_secure_installation

Por último, tuve que ajustar los privilegios de autenticación de usuario. sudo mysql SELECT user,authentication_string,plugin,host FROM mysql.user;

Con este comando, establecemos una contraseña para el usuario root. ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

Para que los cambios tengan efecto. FLUSH PRIVILEGES;

Salimos de mysql para autenticarnos como root. exit

Page 42: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

36

mysql -u root -p

Creamos un nuevo usuario y establecemos sus permisos CREATE USER 'sammy'@'localhost' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON *.* TO 'sammy'@'localhost' WITH GRANT OPTION;

Después de esto salimos de mysql y comprobamos que el servicio funciona. exit systemctl status mysql.service

7.3.2.2 Instalación de los nodos Bitcoin y Lightning Network.

En un primer momento para realizar las pruebas con el protocolo Lightning Network, tuve que

instalar tanto el nodo Bitcoin como el de Lightning Network.

Escribí el siguiente script para automatizar la instalación y así poder hacer instalaciones limpias

rápidamente.

#!/bin/bash echo 1/7 sudo apt-get install golang-1.10-go export GOPATH=~/gocode ln -s /usr/local/bin/go /bin/go export PATH=$PATH:$GOPATH/bin echo 2/7 go get -u github.com/golang/dep/cmd/dep echo 3/7 go get -d github.com/lightningnetwork/lnd cd $GOPATH/src/github.com/lightningnetwork/lnd echo 4/7 make && make install cd $GOPATH/src/github.com/lightningnetwork/lnd echo 5/7 git pull echo 6/7 make && make install echo 7/7 make btcd ln -s $GOPATH/bin/lnd /bin/lnd ln -s $GOPATH/bin/btcd /bin/btcd

7.4. Problemas encontrados con Lightning Network Una vez entrado en materia, surgieron varios problemas a los cuales ni yo, ni los desarrolladores

del daemon utilizado (LND) supimos darle respuesta. Por todo ello se optó de acuerdo con mi

tutor, José Juan Hernández Cabrera, realizar un mock tanto de la blockchain como del protocolo

lightning network a través de una base de datos.

7.5 Explicación del código El proyecto está desarrollado en el lenguaje de programación Java y usa de la herramienta

Maven. Es muy eficaz para configurar el proyecto, así como también facilita la importación de

las librerías necesarias para su correcto funcionamiento.

Los pasos que seguí en el desarrollo se detallan en el punto Metodología.

7.5.1 pom.xml

A continuación, se muestra cual es el contenido del fichero pom.xml.

Page 43: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

37

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jorgefernandez.tft</groupId> <artifactId>BlockLotto</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>BlockLotto Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties>

El proyecto se compila en la versión 1.7 del JDK.

<dependencies> <!-- TEST --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- JERSEY --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.10.19</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-json</artifactId> <version>1.19.4</version> </dependency> <dependency> <groupId>com.sun.jersey.contribs</groupId> <artifactId>jersey-guice</artifactId> <version>1.19.4</version> </dependency> <!-- BBDD --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.12</version> </dependency>

Se incluyen dependencias para ejecutar las siguientes funcionalidades:

• junit: Permite la realización de pruebas para comprobar si el código funciona

correctamente.

• jersey-guice: Permite la creación del servicio web e inyección de la interfaz.

• mysql-connector-java: Permite la comunicación entre el proyecto y la base de datos Mysql.

Page 44: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

38

<!-- ENCRYPT --> <dependency> <groupId>org.mindrot</groupId> <artifactId>jbcrypt</artifactId> <version>0.4</version> </dependency> <!-- GENRANDOM --> <dependency> <groupId>org.bitbucket.dollar</groupId> <artifactId>dollar</artifactId> <version>1.0-beta3</version> </dependency> <!-- QUARTZ --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.2.1</version> </dependency> <dependency> <groupId>javax.transaction</groupId> <artifactId>jta</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.5</version> </dependency> <!-- NEEDED --> <dependency> <groupId>com.googlecode.json-simple</groupId> <artifactId>json-simple</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.11</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.4</version> </dependency> </dependencies>

• jbcrypt: Permite encriptar las contraseñas almacenadas en la base de datos.

• dollar: Permite generar cadenas aleatorias de caracteres.

• quartz: Permite programar eventos como pueden ser el momento de celebración de los

sorteos.

• En el último apartado aparecen librerías necesarias para que el proyecto no de errores o

advertencias.

Page 45: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

39

<build> <finalName>BlockLotto</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.0.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.0</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build> </project>

7.5.2 Main.java

En la clase Main se configura el proyecto con Jersey y Guice para Inyectar la interfaz

LightningAccessor.class a MockLightningAccessor.class. A su vez hacemos uso también de

Jackson para poder utilizar la función de @Consume y @Produce que se usará para poder recibir

peticiones en nuestro servidor web pasando un Json y devolver también un Json con la

respuesta. Esto lo veremos en el apartado 5.3.3.4.

package com.jorgefernandez.tft.blocklotto.service; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Singleton; import com.google.inject.servlet.GuiceServletContextListener; import com.jorgefernandez.tft.blocklotto.resources.lightning.LightningAccessor; import com.jorgefernandez.tft.blocklotto.resources.lightning.MockLightningAccessor; import com.sun.jersey.guice.JerseyServletModule; import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; import org.codehaus.jackson.jaxrs.JacksonJsonProvider; public class Main extends GuiceServletContextListener { @Override protected Injector getInjector() { return Guice.createInjector(new JerseyServletModule() { @Override protected void configureServlets() { bind(LightningAccessor.class).to(MockLightningAccessor.class); serve("/*").with(GuiceContainer.class); bind(BlockLottoService.class); bind(JacksonJsonProvider.class).in(Singleton.class); } }); } }

Page 46: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

40

7.5.3 Interfaz

En este apartado se muestra los métodos que forman parte de la interfaz de Lightning Network.

package com.jorgefernandez.tft.blocklotto.resources.lightning; import com.jorgefernandez.tft.blocklotto.resources.lightning.objects.*; import java.util.List; public interface LightningAccessor { Wallet createWallet(Wallet wallet); Wallet unlockWallet(Wallet wallet); boolean deleteWallet(Wallet wallet); WalletBalance getWalletBalance(String codWallet); boolean createPeer(String nodeA, String nodeB); boolean deletePeer(String nodeA, String nodeB); Channel openChannel(String walletA, String walletB, long amountA, long amountB); void closeChannel(String channelPoint); Invoice createInvoice(String codWallet, long amount); String sendPaymentWithPayReq(String payReq, String codWallet, String concept); Wallet restoreWallet(Wallet wallet); WalletBalance withdrawFunds(String walletID); List<PaymentMoves> getAllPaymentMovesByWallet(Wallet wallet); BalanceInChannels getTotalBalanceInChannels(Wallet wallet); Message transferCoin(String id, String id1, long amount); long calculateChannelCapacity(String codWallet, long amount); List<ChannelRoute> getPaymentRouteChannel(String codWalletInitial, String codWalletFinal, long amount); }

7.5.4 Fichero de configuración

En el fichero de configuración guardamos tanto el nombre de la cartera que hará las funciones

de venta de boletos y pago de premios, como también se establece la ruta donde está ubicado

el fichero donde están almacenadas las palabras para la generación de la frase de restauración

de la cartera. Para tener acceso a estas variables desde cualquier parte del proyecto, se usa el

patrón Singleton.

package com.jorgefernandez.tft.blocklotto.resources.tools; import java.util.HashMap; import java.util.Map; public class Configuration { private static Configuration single_instance = null; public String masterWallet = "master"; //Dirección del archivo words.txt public String path = "C:\\Users\\Jorge\\Documents\\GitHub\\BlockLotto\\"; //Windows //public String path = "/opt/tomcat/webapps/"; //Linux private Configuration() { } public static Configuration getInstance() { if (single_instance == null) single_instance = new Configuration(); return single_instance; } }

Page 47: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

41

7.5.5 BlockLottoService

Se puede observar cómo se inyecta la interfaz en la clase.

package com.jorgefernandez.tft.blocklotto.service; import com.google.inject.Inject; import com.google.inject.Singleton; import com.jorgefernandez.tft.blocklotto.resources.bbdd.MysqlDB; import com.jorgefernandez.tft.blocklotto.resources.lightning.LightningAccessor; import com.jorgefernandez.tft.blocklotto.resources.lightning.objects.*; import com.jorgefernandez.tft.blocklotto.resources.raffles.ListRaffles; import com.jorgefernandez.tft.blocklotto.resources.raffles.ManageRaffles; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import java.util.ArrayList; import java.util.List; @Singleton @Path("/") public class BlockLottoService { private LightningAccessor lightningAccessor; @Inject public BlockLottoService(LightningAccessor lightningAccessor) { this.lightningAccessor = lightningAccessor; }

//New Wallet @POST @Path("/nw") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public Wallet newWallet(Wallet wallet) { return lightningAccessor.createWallet(wallet); } //Wallet Balance @POST @Path("/wb") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public WalletBalance walletBalance(Wallet wallet) { return lightningAccessor.getWalletBalance(wallet.getId()); } //Buy Raffle @POST @Path("/br") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public BuyRaffle buyRaffle(BuyRaffle buyRaffle) { return new ManageRaffles().buyTickets(buyRaffle); }

Como muestra, se muestran solo tres métodos de ejemplo. Se puede observar cómo se utiliza

el método POST para la comunicación con los mismos, su dirección y el tipo de fichero de

entrada y salida. En este caso se usa Json como fichero de intercambio de datos.

A continuación, se explicará el código necesario para la ejecución de cada método.

7.5.5.1 Crear cartera

Con este método creamos la cartera necesaria para poder operar con el sistema. El usuario tiene

que pasar un Json con un campo “pass” de al menos 8 caracteres.

//New Wallet @POST @Path("/nw") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public Wallet newWallet(Wallet wallet) { return lightningAccessor.createWallet(wallet); }

Page 48: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

42

Se encripta la contraseña con la librería BCrypt y se generan las cadenas de caracteres aleatorias

de id, pub y address. La generación es aleatoria ya que este proyecto es una simulación. Se

realiza una comprobación en la base de datos de si la cadena generada ya existe en la misma.

En caso de existir, se vuelve a generar una nueva cadena.

Después de esto se genera un listado aleatorio de 24 palabras las cuales son extraídas del fichero

words.txt. Una vez generadas, obtenemos el hash de la cadena y eso es lo que encriptamos e

introducimos en la base de datos. Se obtiene el hash de la cadena de 24 palabras, ya que la

librería Bcrypt únicamente encripta los primeros 64 caracteres y en muchas ocasiones la string,

supera las 120.

@Override public Wallet createWallet(Wallet wallet) { if (wallet.getPass().length() >= 8) { float initAmount = 1f; String pass = BCrypt.hashpw(wallet.getPass(), BCrypt.gensalt()); String id = initLNDNode(nextFreePort()); String pub = createPUBString(66); String address = createAddressString(34); List<String> words = generateRandomWords(); String encryptedWords = BCrypt.hashpw(wordsToString(words), BCrypt.gensalt()); new MysqlDB().addWallet(id, pub, address, initAmount, pass, encryptedWords); wallet.setId(id); wallet.setPub(pub); wallet.setAddress(address); wallet.setSeedWords(words); wallet.setAmount(initAmount); wallet.setUnlock(true); } return wallet; }

Por último, se inserta la información de la cartera en la base de datos y se rellena la información

en el objeto wallet. Este objeto es devuelto al usuario en formato Json.

public void addWallet(String walletID, String pub, String address, float amount, String pass, String backupWords) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("INSERT INTO wallets(id,pub,address,amount,pass,backupWords,initialAmount) " + "VALUES (?,?,?,?,?,?,?)"); p.setString(1, walletID); p.setString(2, pub); p.setString(3, address); p.setFloat(4, amount); p.setString(5, pass); p.setString(6, backupWords); p.setFloat(7, amount); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

7.5.5.2 Restaurar cartera

Permite recuperar una cartera siempre y cuando tengamos las 24 palabras generadas en el

momento de la creación de esta. El usuario tiene que pasar un Json con un campo “pass” de al

menos 8 caracteres y otro campo “seedWords” con un listado de 24 palabras.

Page 49: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

43

//Restore Wallet @POST @Path("/rw") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public Wallet restoreWallet(Wallet wallet) { return lightningAccessor.restoreWallet(wallet); }

Comprobamos en todas las carteras alojadas en el sistema, si alguna coincide en las 24 palabras

de generación que ha introducido el usuario.

public Wallet restoreWallet(Wallet wallet) { MysqlDB mysqlDB = new MysqlDB(); ResultSet rs = mysqlDB.getAllWallets(); try { while (rs.next()) { if (BCrypt.checkpw(wordsToString(wallet.getSeedWords()), rs.getString("backupWords"))) { wallet.setId(rs.getString("id")); wallet.setPub(rs.getString("pub")); wallet.setAddress(rs.getString("address")); wallet.setAmount(rs.getFloat("amount")); wallet.setUnlock(true); mysqlDB.updateWalletPass(rs.getString("id"), BCrypt.hashpw(wallet.getPass(), BCrypt.gensalt())); break; } } } catch (SQLException e) { e.printStackTrace(); } finally { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } return wallet; }

public ResultSet getAllWallets() { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.wallets.* " + "FROM blocklotto.wallets"); return p.executeQuery(); } } catch (SQLException e) { e.printStackTrace(); } return null; }

Pasamos las palabras suministradas, a una string de palabras separadas por espacios y

generamos el hash de esa cadena de caracteres.

public static String wordsToString(List<String> words) { StringBuilder s = new StringBuilder(); for (String temp : words) { s.append(temp).append(" "); } return getHashText(s.toString().trim()); }

public static String getHashText(String s) { return org.apache.commons.codec.digest.DigestUtils.sha256Hex(s); }

Page 50: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

44

public void updateWalletPass(String walletID, String pass) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("UPDATE blocklotto.wallets SET pass=? " + "WHERE blocklotto.wallets.id=?"); p.setString(1, pass); p.setString(2, walletID); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

7.5.5.3 Desbloquear cartera

Permite desbloquear una cartera después de que el nodo Lightning se haya reiniciado. El usuario

tiene que pasar un Json con un campo “pass” de al menos 8 caracteres y otro campo “id” con el

identificador de su cartera.

//Unlock Wallet @POST @Path("/uw") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public Wallet unlockWallet(Wallet wallet) { return lightningAccessor.unlockWallet(wallet); }

Desbloqueamos la cartera si la contraseña suministrada coincide con la que está almacenada en

él sistema.

@Override public Wallet unlockWallet(Wallet wallet) { ResultSet rs = new MysqlDB().getWalletByWalletID(wallet.getId()); try { if (rs.next()) { if (BCrypt.checkpw(wallet.getPass(), rs.getString("pass"))) { wallet.setPub(rs.getString("pub")); wallet.setAddress(rs.getString("address")); wallet.setUnlock(true); } } } catch (SQLException e) { e.printStackTrace(); }finally{ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } return wallet; }

public ResultSet getWalletByWalletID(String walletID) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.wallets.* " + "FROM blocklotto.wallets " + "WHERE blocklotto.wallets.id=?"); p.setString(1, walletID); return p.executeQuery(); } } catch (SQLException e) { e.printStackTrace(); } return null; }

7.5.5.4 Consultar saldo de la cartera

Permite la consulta de saldo de la cartera. El usuario tiene que pasar un Json con un campo “id”

con la id de su cartera.

Page 51: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

45

//Wallet Balance @POST @Path("/wb") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public WalletBalance walletBalance(Wallet wallet) { return lightningAccessor.getWalletBalance(wallet.getId()); }

Se consulta la información del wallet a través del método “getWalletByWalletID” y se almacena

en el objeto walletBalance que es devuelto al usuario.

@Override public WalletBalance getWalletBalance(String codWallet) { WalletBalance walletBalance = new WalletBalance(); MysqlDB mysqlDB = new MysqlDB(); ResultSet rs = mysqlDB.getWalletByWalletID(codWallet); try { while (rs.next()) { walletBalance.setTotal_balance(rs.getDouble("amount")); walletBalance.setConfirmed_balance(rs.getDouble("amount")); walletBalance.setUnconfirmed_balance(0); } } catch (SQLException e) { e.printStackTrace(); } return walletBalance; }

7.5.5.5 Comprar boletos

Permite al usuario la compra de boletos para un sorteo específico. El usuario tiene que pasar un

Json con un campo “id” con el identificador de su cartera, un campo “codRaffle” con el

identificador del sorteo y por último un campo “number” con el número de boletos que quiere

comprar.

//Buy Raffle @POST @Path("/br") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public BuyRaffle buyRaffle(BuyRaffle buyRaffle) { return new ManageRaffles().buyTickets(buyRaffle); }

public BuyRaffle buyTickets(BuyRaffle buyRaffle) { MysqlDB mysqlDB = new MysqlDB(); MockLightningAccessor mockLightning = new MockLightningAccessor(); buyRaffle.setMessage("Error"); if (mysqlDB.checkRaffleisBlocked(buyRaffle.getCodRaffle())) return buyRaffle; long l = mysqlDB.getPriceByBuyedTickets(buyRaffle.getCodRaffle(), buyRaffle.getNumber()); if (mysqlDB.getRemainingTickets(buyRaffle.getCodRaffle()) >= buyRaffle.getNumber()) { Invoice invoice = mockLightning.createInvoice(masterWallet, l); if (!mockLightning.sendPaymentWithPayReq(invoice.getPay_req(), buyRaffle.getId(), "Compra de boletos").isEmpty()) { for (int i = 0; i < buyRaffle.getNumber(); i++) { mysqlDB.addBuyedTickets(buyRaffle.getCodRaffle(), createRaffleNumberString(5), buyRaffle.getId()); } updateRafflePrize(buyRaffle.getCodRaffle(), l); buyRaffle.setMessage("Transaction completed"); buyRaffle.setTickets(mysqlDB.getTicketsNumbersByRaffleAndWallet(buyRaffle.getCodRaffle(), buyRaffle.getId())); } } return buyRaffle; }

En primer lugar, se comprueba si el sorteo está bloqueado.

Page 52: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

46

public boolean checkRaffleisBlocked(int codRaffle) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.raffles.* " + "FROM blocklotto.raffles " + "WHERE blocklotto.raffles.id=? AND blocklotto.raffles.blocked=0"); p.setInt(1, codRaffle); p.executeQuery(); ResultSet rs = p.getResultSet(); if (rs.next()) { return false; } rs.close(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return true; }

Se obtiene el importe que hay que pagar para comprar los boletos de ese tipo de sorteo.

public int getPriceByBuyedTickets(int codRaffle, int number) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.raffleTypes.price " + "FROM blocklotto.raffleTypes " + "INNER JOIN blocklotto.raffles " + "WHERE blocklotto.raffleTypes.id = blocklotto.raffles.type " + "AND blocklotto.raffles.id =?"); p.setInt(1, codRaffle); p.executeQuery(); ResultSet rs = p.getResultSet(); if (rs.next()) { return rs.getInt("price") * number; } rs.close(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return 0; }

Page 53: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

47

Comprobamos la disponibilidad del número de boletos que se quieren comprar.

public int getRemainingTickets(int idRaffle) { Connection connection = connection(); PreparedStatement p = null; ResultSet rs = null; try { if (connection != null) { p = connection.prepareStatement("SELECT COUNT(blocklotto.raffleNumbers.number) AS nTickets, blocklotto.raffleTypes.maxTickets " + "FROM blocklotto.raffleNumbers " + "INNER JOIN blocklotto.raffleTypes " + "INNER JOIN blocklotto.raffles " + "WHERE blocklotto.raffleNumbers.codRaffle = blocklotto.raffles.id " + "AND blocklotto.raffles.type = blocklotto.raffleTypes.id " + "AND blocklotto.raffles.id=?"); p.setInt(1, idRaffle); p.executeQuery(); rs = p.getResultSet(); if (rs.next()) { return rs.getInt("maxTickets") - rs.getInt("nTickets"); } } } catch (SQLException e) { e.printStackTrace(); } finally { try { rs.close(); p.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); } } return 0; }

Se crea la petición por parte de la cartera maestra del importe que cuestan los boletos.

@Override public Invoice createInvoice(String codWallet, long amount) { Invoice invoice = new Invoice(); if (codWallet != null) { String payReq = createPayReqString(189); int i = new MysqlDB().getCountPaymentsRequestByCodWallet(codWallet) + 1; if (new MysqlDB().addPaymentRequest(codWallet, payReq, amount, 0, i) > 0) { invoice.setPay_req(payReq); invoice.setAdd_index(i); } } return invoice; }

Lightning Network lleva el control de la cantidad de requerimientos de pago que efectúa una

misma cartera. Se obtiene el total de requerimientos de pago que ha efectuado la cartera master

para así posteriormente cuando se cree el nuevo requerimiento, añadamos uno al contador.

public int getCountPaymentsRequestByCodWallet(String codWallet) { int maxIndex = 0; try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT MAX(blocklotto.paymentsRequest.addIndex) AS maxIndex " + "FROM blocklotto.paymentsRequest " + "WHERE blocklotto.paymentsRequest.codWalletRequest=?"); p.setString(1, codWallet); p.executeQuery(); ResultSet rs = p.getResultSet(); if (rs.next()) { maxIndex = rs.getInt("maxIndex"); } rs.close(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return maxIndex; }

Page 54: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

48

public int addPaymentRequest(String codWallet, String payRequest, long amount, int payed, int addIndex) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("INSERT INTO " + "blocklotto.paymentsRequest(payReq, codWalletRequest, amount, payed, addIndex) " + "VALUES(?,?,?,?,?)", Statement.RETURN_GENERATED_KEYS); p.setString(1, payRequest); p.setString(2, codWallet); p.setLong(3, amount); p.setInt(4, payed); p.setInt(5, addIndex); int i = p.executeUpdate(); p.close(); connection.close(); return i; } } catch (SQLException e) { e.printStackTrace(); } return -1; }

Una vez creado el requerimiento, ya se puede realizar el pago.

@Override public String sendPaymentWithPayReq(String payReq, String walletA, String concept) { MysqlDB mysqlDB = new MysqlDB(); String walletB = mysqlDB.getWalletByPayReq(payReq); long amount = mysqlDB.getAmountByPayReq(payReq); List<ChannelRoute> channelRoutes = new ArrayList<>(); if (!walletA.equals(masterWallet)) channelRoutes = getPaymentRouteChannel(walletA, walletB, amount); String fundingTxID = ""; if (channelRoutes.size() > 0) { for (ChannelRoute channelRoute : channelRoutes) { mysqlDB.updateChannelBalance(channelRoute.getFundingTxID(), amount, channelRoute.isReverse()); fundingTxID = channelRoute.getFundingTxID(); } } else { long l = calculateChannelCapacity(walletA, amount); if (l != 0) { createPeer(walletA, walletB); if (walletA.equals(masterWallet)) { fundingTxID = openChannel(walletA, walletB, Math.round(amount * 1.01f), amount).getFunding_txid(); } else { fundingTxID = openChannel(walletA, walletB, l, amount).getFunding_txid(); } } else { return ""; } } mysqlDB.addPaymentsSend(payReq, walletA); mysqlDB.addPaymentMovement(walletA, walletB, amount, getCurrentTime(), concept); mysqlDB.setPayedInvoice(payReq); return fundingTxID; }

Se obtiene el identificador de la cartera que requirió el pago. En este caso se trata de la cartera

master.

public String getWalletByPayReq(String payReq) { String wallet = ""; try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.paymentsRequest.codWalletRequest " + "FROM blocklotto.paymentsRequest " + "WHERE blocklotto.paymentsRequest.payReq=?"); p.setString(1, payReq); p.executeQuery(); ResultSet rs = p.getResultSet(); if (rs.next()) { wallet = rs.getString("codWalletRequest"); } rs.close(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return wallet; }

Page 55: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

49

Se obtiene el importe a pagar del requerimiento de pago.

public long getAmountByPayReq(String payReq) { long amount = 0; try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.paymentsRequest.amount " + "FROM blocklotto.paymentsRequest " + "WHERE blocklotto.paymentsRequest.payReq=?"); p.setString(1, payReq); p.executeQuery(); ResultSet rs = p.getResultSet(); if (rs.next()) { amount = rs.getLong("amount"); } rs.close(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return amount; }

Se calcula la ruta de canales más corta para realizar el pago. Para ello se utiliza un método

recursivo. En caso de no encontrar una ruta válida, se creará un nuevo canal directo entre el

usuario y el receptor del pago, en este caso el master.

public List<ChannelRoute> getPaymentRouteChannel(String codWalletInitial, String codWalletFinal, long amount) { List<ChannelRoute> channelRoutes = new ArrayList<>(); List<ChannelRoute> channelRoutes2 = new ArrayList<>(); List<ChannelRoute> channelRoutes3 = new ArrayList<>(); List<ChannelRoute> channelRoutes4 = new ArrayList<>(); if (new MysqlDB().getChannelRoute(codWalletInitial, codWalletFinal, amount, channelRoutes, new ArrayList<>(), "ORDER BY blocklotto.channels.codWalletRemote ASC").size() > 1) if (new MysqlDB().getChannelRoute(codWalletInitial, codWalletFinal, amount, channelRoutes2, new ArrayList<>(), "ORDER BY blocklotto.channels.codWalletLocal DESC").size() > 1) if (new MysqlDB().getChannelRoute(codWalletInitial, codWalletFinal, amount, channelRoutes3, new ArrayList<>(), "ORDER BY blocklotto.channels.codWalletLocal ASC").size() > 1) new MysqlDB().getChannelRoute(codWalletInitial, codWalletFinal, amount, channelRoutes4, new ArrayList<>(), "ORDER BY blocklotto.channels.codWalletRemote DESC"); if (channelRoutes2.size() <= channelRoutes.size() && channelRoutes2.size() != 0) channelRoutes = channelRoutes2; if (channelRoutes3.size() <= channelRoutes.size() && channelRoutes3.size() != 0) channelRoutes = channelRoutes3; if (channelRoutes4.size() <= channelRoutes.size() && channelRoutes4.size() != 0) channelRoutes = channelRoutes4; return channelRoutes; }

Page 56: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

50

El método recursivo parece tan complicado, ya que los canales son bidireccionales. Se

comprueba si la walletIni es local o remota en cada canal. Esto es importante ya que la walletIni

de ser la cartera local se tiene que comprobar el saldo local y si fuera la cartera remota, se

comprobaría el saldo remoto.

public List<ChannelRoute> getChannelRoute(String walletIni, String walletFin, long amount, List<ChannelRoute> channelRoutes, List<String> fundingList, String order) { if (!walletIni.equals(walletFin)) { Connection connection = connection(); PreparedStatement p = null; ResultSet rs = null; try { if (connection != null) { p = connection.prepareStatement("SELECT blocklotto.channels.* FROM blocklotto.channels WHERE blocklotto.channels.active=1 AND (blocklotto.channels.codWalletLocal=? OR blocklotto.channels.codWalletRemote=?) " + order); p.setString(1, walletIni); p.setString(2, walletIni); rs = p.executeQuery(); while (rs.next()) { if (!fundingList.contains(rs.getString("fundingTxID"))) { fundingList.add(rs.getString("fundingTxID")); if (walletIni.equals(rs.getString("codWalletLocal"))) { if (rs.getLong("balanceLocal") >= amount) { if (rs.getString("codWalletRemote").equals(walletFin)) { channelRoutes.add(new ChannelRoute(rs.getString("codWalletLocal"), rs.getString("codWalletRemote"), rs.getString("fundingTxID"), false)); return channelRoutes; } else { if (!channelRoutes.contains(new ChannelRoute(rs.getString("codWalletLocal"), rs.getString("codWalletRemote"), rs.getString("fundingTxID"), false))) { channelRoutes.add(new ChannelRoute(rs.getString("codWalletLocal"), rs.getString("codWalletRemote"), rs.getString("fundingTxID"), false)); } channelRoutes = getChannelRoute(rs.getString("codWalletRemote"), walletFin, amount, channelRoutes, fundingList, order); if (channelRoutes.size() > 0) { if (channelRoutes.get(channelRoutes.size() - 1).getWalletFinal().equals(walletFin)) { return channelRoutes; } } } } } else { if (rs.getLong("balanceRemote") >= amount) { if (rs.getString("codWalletLocal").equals(walletFin)) { channelRoutes.add(new ChannelRoute(rs.getString("codWalletRemote"), rs.getString("codWalletLocal"), rs.getString("fundingTxID"), true)); return channelRoutes; } else { if (!channelRoutes.contains(new ChannelRoute(rs.getString("codWalletRemote"), rs.getString("codWalletLocal"), rs.getString("fundingTxID"), true))) { channelRoutes.add(new ChannelRoute(rs.getString("codWalletRemote"), rs.getString("codWalletLocal"), rs.getString("fundingTxID"), true)); } channelRoutes = getChannelRoute(rs.getString("codWalletLocal"), walletFin, amount, channelRoutes, fundingList, order); if (channelRoutes.size() > 0) { if (channelRoutes.get(channelRoutes.size() - 1).getWalletFinal().equals(walletFin)) { return channelRoutes; } } } } } } } if (channelRoutes.size() > 0) { channelRoutes.remove(channelRoutes.size() - 1); return channelRoutes; } } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rs != null) { rs.close(); } if (p != null) { p.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } } return channelRoutes; }

Page 57: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

51

Se actualizan los saldos internos de todos los canales implicados en la transacción.

public void updateChannelBalance(String fundingTxID, long amount, boolean reverse) { try { ResultSet rs = getChannelByfundingTxID(fundingTxID); Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("UPDATE blocklotto.channels SET " + "blocklotto.channels.balanceLocal=?," + "blocklotto.channels.balanceRemote=?," + "blocklotto.channels.numUpdates=? " + "WHERE blocklotto.channels.fundingTxID=?"); if (rs != null) while (rs.next()) { if (reverse) { p.setLong(1, rs.getLong("balanceLocal") + amount); p.setLong(2, rs.getLong("balanceRemote") - amount); } else { p.setLong(1, rs.getLong("balanceLocal") - amount); p.setLong(2, rs.getLong("balanceRemote") + amount); } p.setInt(3, (rs.getInt("numUpdates") + 2)); p.setString(4, fundingTxID); p.execute(); } p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

private ResultSet getChannelByfundingTxID(String fundingTxID) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.channels.* " + "FROM blocklotto.channels " + "WHERE blocklotto.channels.fundingTxID=?"); p.setString(1, fundingTxID); return p.executeQuery(); } } catch (SQLException e) { e.printStackTrace(); } return null; }

Se calcula la capacidad que debe tener el canal. Para ello se tiene en cuenta que la creación de

un canal viene siempre ligada al pago de una comisión de 9050 satoshis. Por otro lado, también

hay que tener en cuenta que, al realizar el pago, se debe quedar en la parte del canal del que

paga al menos un uno por ciento de la capacidad del canal. Lightning Network Daemon actúa de

esta manera.

Se ha estipulado para un mayor aprovechamiento del protocolo Lightning, que cuando vayamos

a comprar boletos y o bien no tengamos suficiente saldo en nuestros canales o bien sea la

primera vez que compremos y el importe no supere los 2.000.000 de satoshis, el canal tenga esa

capacidad de satoshis. Así en el futuro, el pago, en caso de suficiente saldo, se realizará a través

de ese mismo canal. En esto se basa el pago a través de Lightning. Sería bueno que siempre

hubiera un canal con suficiente saldo hacia el receptor, para poder realizar el pago

instantáneamente.

Page 58: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

52

public long calculateChannelCapacity(String codWallet, long amount) { long l = convertBTCtoSatoshis(getWalletBalance(codWallet).getTotal_balance()); amount = Math.round((amount * 1.01f) + 9050); if (l >= amount) { if (amount >= 2000000L) { return amount; } else { if (l < 2000000L) { return amount; } else { return 2000000L; } } } return 0L; }

public static long convertBTCtoSatoshis(Double d) { return Math.round(d * 100000000); }

Para poder realizar un pago es necesario que exista una conexión entre los dos nodos. En caso

de no existir la conexión, esta se crea.

@Override public boolean createPeer(String nodeA, String nodeB) { if (!nodeA.equals(nodeB)) return new MysqlDB().addPeer(nodeA, nodeB); return false; }

public boolean addPeer(String nodeA, String nodeB) { if (!checkPeer(nodeA, nodeB)) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("INSERT INTO peers(codWalletA,codWalletB) VALUES (?,?)"); p.setString(1, nodeA); p.setString(2, nodeB); p.execute(); p.close(); connection.close(); } return true; } catch (SQLException e) { e.printStackTrace(); } } return false; }

public boolean checkPeer(String nodeA, String nodeB) { Connection connection = connection(); try { if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT * FROM blocklotto.peers " + "WHERE (blocklotto.peers.codWalletA=? AND blocklotto.peers.codWalletB=?) " + "OR (blocklotto.peers.codWalletA=? AND blocklotto.peers.codWalletB=?)"); p.setString(1, nodeA); p.setString(2, nodeB); p.setString(3, nodeB); p.setString(4, nodeA); boolean b = checkIfExist(p); p.close(); connection.close(); return b; } } catch (SQLException e) { e.printStackTrace(); } return false; }

Page 59: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

53

private boolean checkIfExist(PreparedStatement p) { try { p.execute(); ResultSet rs = p.getResultSet(); if (rs.next()) { return true; } rs.close(); p.close(); } catch (SQLException e) { e.printStackTrace(); } return false; }

En caso de no haber encontrado una ruta ya existente válida para la transferencia, es el

momento de abrir el canal y añadir los fondos al mismo

@Override public Channel openChannel(String walletLocal, String walletRemote, long balanceLocal, long balanceRemote) { MysqlDB mysqlDB = new MysqlDB(); Channel openChannel = new Channel(); if (mysqlDB.checkPeer(walletLocal, walletRemote)) { String fundingTxID = createFundingTxIDString(64); openChannel.setFunding_txid(fundingTxID); if (mysqlDB.addChannel(fundingTxID, walletLocal, walletRemote, balanceLocal, balanceRemote)) mysqlDB.updateAmountWallet(walletLocal, balanceLocal, false); return openChannel; } else { openChannel.setErrorMessage("Error: Must exist a connection between nodes."); } return openChannel; }

public boolean addChannel(String fundingTxID, String localWallet, String remoteWallet, long balanceLocal, long balanceRemote) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("INSERT INTO " + "blocklotto.channels(fundingTxID,active,codWalletLocal,codWalletRemote,capacity,balanceLocal,balanceRemote,numUpdates) " + "VALUES(?,?,?,?,?,?,?,?)"); p.setString(1, fundingTxID); p.setBoolean(2, true); p.setString(3, localWallet); p.setString(4, remoteWallet); p.setLong(5, balanceLocal); p.setLong(6, (balanceLocal - balanceRemote - 9050)); p.setLong(7, balanceRemote); p.setLong(8, (balanceRemote != 0) ? 2 : 0); p.execute(); p.close(); connection.close(); return true; } } catch (SQLException e) { e.printStackTrace(); } return false; }

Se actualiza el saldo de la cartera

Page 60: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

54

public void updateAmountWallet(String walletID, long f, boolean add) { try { double i = add ? getAmountByWalletID(walletID) + convertSatoshistoBTC(f) : getAmountByWalletID(walletID) - convertSatoshistoBTC(f); Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("UPDATE blocklotto.wallets " + "SET " + " blocklotto.wallets.amount =? " + "WHERE " + " blocklotto.wallets.id =?"); p.setDouble(1, i); p.setString(2, walletID); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

public double getAmountByWalletID(String walletID) { double amount = 0d; try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.wallets.amount " + "FROM blocklotto.wallets " + "WHERE blocklotto.wallets.id=?"); p.setString(1, walletID); p.executeQuery(); ResultSet rs = p.getResultSet(); if (rs.next()) { amount = rs.getDouble("amount"); } p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return amount; }

public static double convertSatoshistoBTC(long f) { return (double) f / 100000000; }

Se registra en el sistema el pago enviado a la cartera master.

public void addPaymentsSend(String payReq, String codWallet) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("INSERT INTO blocklotto.paymentsSend(codPayReq,codWallet) VALUES(?,?)"); p.setString(1, payReq); p.setString(2, codWallet); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

Se registra en el sistema el movimiento.

Page 61: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

55

public void addPaymentMovement(String fromWallet, String toWallet, long amount, String date, String concept) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("INSERT INTO " + "blocklotto.paymentMoves(fromWallet, toWallet, amount, date,concept) " + "VALUES(?,?,?,?,?)"); p.setString(1, fromWallet); p.setString(2, toWallet); p.setFloat(3, amount); p.setString(4, date); p.setString(5, concept); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

Se marca como pagado el requerimiento de pago.

public void setPayedInvoice(String payReq) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("UPDATE blocklotto.paymentsRequest " + "SET blocklotto.paymentsRequest.payed=1 " + "WHERE blocklotto.paymentsRequest.payReq=?"); p.setString(1, payReq); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

Se registra en el sistema la compra de los boletos.

public void addBuyedTickets(int idRaffle, String number, String codWallet) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("INSERT INTO " + "blocklotto.raffleNumbers(codRaffle,number,codWallet) " + "VALUES(?,?,?)"); p.setInt(1, idRaffle); p.setString(2, number); p.setString(3, codWallet); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

Una vez comprados los boletos, se actualiza el premio del sorteo. Este va cambiando de forma

dinámica conforme se vayan comprando boletos. De esta manera la empresa no pierde dinero

ya que no preestablece un premio desde el principio, con el peligro que conlleva solo se compren

algunos boletos. En la actualidad cuando se crea un sorteo, se estipula un premio inicial de cinco

veces el precio de un boleto. De esta manera se anima a la compra desde el principio.

private void updateRafflePrize(int idRaffle, long prize) { MysqlDB mysqlDB = new MysqlDB(); long l = mysqlDB.getPrizeRaffle(idRaffle) + Math.round(prize * 0.8); new MysqlDB().updateRafflePrize(idRaffle, l); }

Page 62: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

56

public long getPrizeRaffle(int idRaffle) { long prize = 0L; try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.raffles.award " + "FROM blocklotto.raffles " + "WHERE blocklotto.raffles.id=?"); p.setInt(1, idRaffle); p.executeQuery(); ResultSet rs = p.getResultSet(); if (rs.next()) { prize = rs.getLong("award"); } rs.close(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return prize; }

public void updateRafflePrize(int idRaffle, long prize) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("UPDATE blocklotto.raffles " + "SET blocklotto.raffles.award=? " + "WHERE blocklotto.raffles.id=?"); p.setLong(1, prize); p.setInt(2, idRaffle); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

public List<String> getTicketsNumbersByRaffleAndWallet(int idRaffle, String codWallet) { List<String> ticketsList = new ArrayList<>(); try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.raffleNumbers.number " + "FROM blocklotto.raffleNumbers " + "WHERE blocklotto.raffleNumbers.codRaffle =? " + "AND blocklotto.raffleNumbers.codWallet =?"); p.setInt(1, idRaffle); p.setString(2, codWallet); p.executeQuery(); ResultSet rs = p.getResultSet(); while (rs.next()) { ticketsList.add(rs.getString("number")); } rs.close(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return ticketsList; }

7.5.5.6 Consultar saldo en los canales abiertos.

Permite al usuario consultar el saldo en su parte del canal de todos los canales abiertos. El

usuario tiene que pasar un Json con un campo “id” con el identificador de su cartera. Al cerrar

esos canales, el usuario recuperará todo ese saldo y se sumará a lo que tenga en su wallet.

//Total Balance in Channels @POST @Path("/tbc") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public BalanceInChannels totalBalanceInChannels(Wallet wallet) { return lightningAccessor.getTotalBalanceInChannels(wallet); }

Page 63: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

57

Se comprueba si el identificador de la cartera está en la parte local o remota del canal. De ser

así se suma el saldo de dicha parte.

public BalanceInChannels getTotalBalanceInChannels(Wallet wallet) { MysqlDB mysqlDB = new MysqlDB(); ResultSet rs = mysqlDB.getChannelsByCodWallet(wallet.getId()); BalanceInChannels balanceInChannels = new BalanceInChannels(); int amount = 0; try { while (rs.next()) { if (wallet.getId().equals(rs.getString("codWalletLocal"))) { amount += rs.getInt("balanceLocal"); } else { amount += rs.getInt("balanceRemote"); } } } catch (SQLException e) { e.printStackTrace(); } balanceInChannels.setBalance(amount); return balanceInChannels; }

public ResultSet getChannelsByCodWallet(String codWallet) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.channels.* " + "FROM blocklotto.channels " + "WHERE (blocklotto.channels.codWalletLocal=? OR blocklotto.channels.codWalletRemote=?) " + "AND blocklotto.channels.active=1"); p.setString(1, codWallet); p.setString(2, codWallet); return p.executeQuery(); } } catch (SQLException e) { e.printStackTrace(); } return null; }

7.5.5.7 Recuperar saldo de los canales abiertos.

Permite al usuario recuperar todos sus fondos de sus canales. El usuario tiene que pasar un Json

con un campo “id” con el identificador de su cartera.

@Override public WalletBalance withdrawFunds(String walletID) { MysqlDB mysqlDB = new MysqlDB(); ResultSet rs = mysqlDB.getChannelsByCodWallet(walletID); try { while (rs.next()) { closeChannel(rs.getString("fundingTxID")); } } catch (SQLException e) { e.printStackTrace(); } return getWalletBalance(walletID); }

@Override public void closeChannel(String channelPoint) { MysqlDB mysqlDB = new MysqlDB(); mysqlDB.setChannelDeactive(channelPoint); mysqlDB.returnBalanceChannelToWallets(channelPoint); }

Page 64: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

58

Se cierra el canal con lo que ya no está operativo.

public void setChannelDeactive(String channelPoint) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("UPDATE blocklotto.channels " + "SET blocklotto.channels.active=0 " + "WHERE blocklotto.channels.fundingTxID=?"); p.setString(1, channelPoint); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

Se actualizan los saldos de las carteras incluidas en el canal.

public void returnBalanceChannelToWallets(String channelPoint) { ResultSet rs = getChannelByfundingTxID(channelPoint); try { if (rs != null) { while (rs.next()) { updateAmountWallet(rs.getString("codWalletLocal"), (rs.getLong("balanceLocal")), true); updateAmountWallet(rs.getString("codWalletRemote"), (rs.getLong("balanceRemote")), true); } rs.close(); } } catch (SQLException e) { e.printStackTrace(); } }

7.5.5.8 Historial de movimientos

Permite al usuario ver el historial de movimientos. El usuario tiene que pasar un Json con un

campo “id” con el identificador de su cartera.

//Payment moves @POST @Path("/pm") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public List<PaymentMoves> paymentMoves(Wallet wallet) { return lightningAccessor.getAllPaymentMovesByWallet(wallet); }

public List<PaymentMoves> getAllPaymentMovesByWallet(Wallet wallet) { List<PaymentMoves> paymentMoves = new ArrayList<>(); MysqlDB mysqlDB = new MysqlDB(); ResultSet rs = mysqlDB.getPaymentsMovesByWallet(wallet.getId()); long historicalBalance = 0L; boolean firstTimeInCalcHistoricalBalance = true; try { while (rs.next()) { PaymentMoves payment = new PaymentMoves(); historicalBalance = calcHistoricalBalance(wallet, rs, historicalBalance, firstTimeInCalcHistoricalBalance); firstTimeInCalcHistoricalBalance = false; setPaymentInformation(wallet, paymentMoves, rs, historicalBalance, payment); } } catch ( SQLException e1) { e1.printStackTrace(); } Collections.reverse(paymentMoves); return paymentMoves; }

Page 65: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

59

Se obtienen todos los movimientos de una cartera y se calcula el saldo histórico en cada uno de

esos movimientos. Al final se devuelve al usuario un listado de movimientos de pago.

public ResultSet getPaymentsMovesByWallet(String codWallet) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.paymentMoves.*, blocklotto.wallets.initialAmount " + "FROM blocklotto.paymentMoves " + "INNER JOIN blocklotto.wallets ON " + "(blocklotto.wallets.id = blocklotto.paymentMoves.fromWallet OR blocklotto.wallets.id = blocklotto.paymentMoves.toWallet) " + "WHERE blocklotto.wallets.id =?"); p.setString(1, codWallet); return p.executeQuery(); } } catch (SQLException e) { e.printStackTrace(); } return null; }

private long calcHistoricalBalance(Wallet wallet, ResultSet rs, long historicalBalance, boolean aux) throws SQLException { if (aux) { historicalBalance = Tools.convertBTCtoSatoshis(rs.getDouble("initialAmount")); } if (wallet.getId().equals(rs.getString("fromWallet"))) { historicalBalance = historicalBalance - (new BigDecimal(rs.getInt("amount")).longValue()); } else { historicalBalance = historicalBalance + (new BigDecimal(rs.getInt("amount")).longValue()); } return historicalBalance; }

private void setPaymentInformation(Wallet wallet, List<PaymentMoves> paymentMoves, ResultSet rs, long historicalBalance, PaymentMoves payment) throws SQLException { if (wallet.getId().equals(rs.getString("fromWallet"))) { payment.setFrom(wallet.getId()); payment.setTo(rs.getString("toWallet")); payment.setAmount(rs.getInt("amount") * -1); payment.setAction("send"); } else { payment.setFrom(rs.getString("fromWallet")); payment.setTo(wallet.getId()); payment.setAmount(rs.getInt("amount")); payment.setAction("receive"); } payment.setConcept(rs.getString("concept")); payment.setHistoricalAmount(historicalBalance); payment.setDate(rs.getString("date")); paymentMoves.add(payment); }

7.5.5.9 Realizar transferencias a otros usuarios

Permite al usuario realizar transferencias a otros usuarios con carteras Lightning. Como

Lightning permite las transferencias a través de canales ajenos siempre y cuando tengamos

conexión con ellos y tengamos también saldo suficiente, se simula esta característica. El usuario

tiene que pasar un Json con un campo “id” con el identificador de su cartera, un campo

“toWallet” con el pub de la cartera a la que quiere hacer la transferencia y por último un campo

“amount” con la cantidad de satoshis que se quieren transferir.

Page 66: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

60

Se comprueba que el pub pertenezca a una cartera.

//Payment to other account @POST @Path("/tc") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public Message transferCoin(TransferCoin transferCoin) { String id = new MysqlDB().getWalletIDByPUB(transferCoin.getToWallet()); if (!id.isEmpty()) { return lightningAccessor.transferCoin(transferCoin.getId(), id, transferCoin.getAmount()); } else { Message message = new Message(); message.setMessage("Error"); return message; } }

Se procede a realizar el pago llamando al método “sendPaymentWithPayReq”. Este método ya

se explicó en el apartado Comprar boletos.

public Message transferCoin(String WalletA, String walletB, long amount) { Message message = new Message(); message.setMessage("Error"); if (!WalletA.equals(walletB)) { Invoice invoice = createInvoice(walletB, amount); String channel = sendPaymentWithPayReq(invoice.getPay_req(), WalletA, "Transfer"); if (channel.length() == 64) { message.setMessage("Transfer complete"); } } return message; }

7.5.5.10 Consultar notificaciones

Permite al usuario consultar las notificaciones generadas en caso de haber ganado un premio.

El usuario tiene que pasar un Json con un campo “id” con el identificador de su cartera.

@POST @Path("/notifications") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public List<Notification> notifications(Wallet wallet) { return new ManageRaffles().getNotificationsByWalletID(wallet.getId()); }

Se listan todas las notificaciones relacionadas con una cartera y se devuelve al usuario este

listado con formato Json.

public List<Notification> getNotificationsByWalletID(String codWallet) { List<Notification> notifications = new ArrayList<>(); ResultSet rs = new MysqlDB().getNotificationsByWallet(codWallet); try { while (rs.next()) { Notification notification = new Notification( rs.getInt("id"), rs.getString("codWallet"), rs.getString("date"), rs.getString("winningNumber"), rs.getString("name"), rs.getLong("award"), rs.getInt("readed")); notifications.add(notification); } } catch (SQLException e) { e.printStackTrace(); } return notifications; }

Page 67: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

61

public ResultSet getNotificationsByWallet(String codWallet) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT a.id, a.codWallet, b.date, b.winningNumber, b.award, c.name, a.readed\n" + "FROM blocklotto.notifications AS a " + "INNER JOIN blocklotto.raffles AS b ON a.codRaffle = b.id " + "INNER JOIN blocklotto.raffleTypes AS c ON b.type = c.id " + "WHERE a.codWallet =? " + "ORDER BY b.date DESC"); p.setString(1, codWallet); return p.executeQuery(); } } catch (SQLException e) { e.printStackTrace(); } return null; }

7.5.5.11 Marcar notificaciones como leídas

Permite al usuario marcar como leídas las notificaciones. El usuario tiene que pasar un Json con

un campo “id” con el identificador de la notificación.

@POST @Path("/nr") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public Message MarkNotifications(Notification notification) { new MysqlDB().setNotificationReaded(notification.getId()); Message message = new Message(); message.setMessage((new MysqlDB().checkNotificationReaded(notification.getId())) ? "Readed" : "Error"); return message; }

Se actualiza la notificación a leída.

public void setNotificationReaded(int id) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("UPDATE blocklotto.notifications " + "SET blocklotto.notifications.readed=1 " + "WHERE blocklotto.notifications.id=?"); p.setInt(1, id); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

public boolean checkNotificationReaded(int id) { Connection connection = connection(); try { if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.notifications.id " + "FROM blocklotto.notifications " + "WHERE blocklotto.notifications.id=? AND blocklotto.notifications.readed=1"); p.setInt(1, id); boolean b = checkIfExist(p); p.close(); connection.close(); return b; } } catch (SQLException e) { e.printStackTrace(); } return false; }

Page 68: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

62

7.5.5.12 Lista de todos los sorteos

Permite al usuario listar todos los sorteos. El usuario tiene que pasar un Json con un campo “id”

con el identificador de su cartera.

@POST @Path("/listad") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public List<Raffle> allDraws(Wallet wallet) { return new ListRaffles().getAllRaffles(wallet); }

Se realiza la consulta y se rellena una lista de objetos Raffle que es devuelta al usuario.

public List<Raffle> getAllRaffles(Wallet wallet) { return new MysqlDB().getListRaffles("SELECT \n" + " blocklotto.raffles.id,\n" + " blocklotto.raffleTypes.price,\n" + " blocklotto.raffles.award,\n" + " blocklotto.raffleTypes.maxTickets AS totalParticipations,\n" + " blocklotto.raffleTypes.name,\n" + " blocklotto.raffles.date,\n" + " blocklotto.raffleTypes.info AS information,\n" + " blocklotto.raffleStates.name AS state,\n" + " blocklotto.raffles.winningNumber,\n" + " blocklotto.raffles.blocked\n" + "FROM\n" + " blocklotto.raffles\n" + " INNER JOIN\n" + " blocklotto.raffleTypes ON blocklotto.raffles.type = blocklotto.raffleTypes.id\n" + " INNER JOIN\n" + " blocklotto.raffleStates ON blocklotto.raffles.state = blocklotto.raffleStates.id\n" + "ORDER BY blocklotto.raffles.date DESC", wallet.getId()); }

public List<Raffle> getListRaffles(String sql, String codWallet) { List<Raffle> raffles = new ArrayList<>(); ListRaffles listRaffles = new ListRaffles(); ConnectionControl connectionControl = executeQuery(sql); ResultSet rs = connectionControl.getResultSet(); try { while (rs.next()) { raffles.add(new Raffle( rs.getInt("id"), rs.getInt("price"), rs.getInt("award"), listRaffles.getAmountTicketsBuyedByWalletID(rs.getInt("id"), codWallet), rs.getInt("totalParticipations"), listRaffles.currentParticipation(rs.getInt("id")), rs.getString("name"), rs.getString("date"), rs.getString("information"), listRaffles.getAmountTicketsBuyedByWalletID(rs.getInt("id"), codWallet) * rs.getInt("price"), rs.getString("state"), rs.getString("winningNumber"), (rs.getInt("blocked") == 1) ? 1 : (getRemainingTickets(rs.getInt("id")) == 0) ? 1 : 0)); } } catch (SQLException e) { e.printStackTrace(); } finally { closeConnection(connectionControl); } return raffles; }

7.5.5.13 Lista de los sorteos pendientes de celebración.

Permite al usuario listar todos los sorteos. El usuario tiene que pasar un Json con un campo “id”

con el identificador de su cartera.

@POST @Path("/listud") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public List<Raffle> upcomingDraws(Wallet wallet) { return new ListRaffles().getUpcomingRaffles(wallet); }

Page 69: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

63

Se consultan los sorteos pendientes.

public List<Raffle> getUpcomingRaffles(Wallet wallet) { return new MysqlDB().getListRaffles("SELECT \n" + " blocklotto.raffles.id,\n" + " blocklotto.raffleTypes.price,\n" + " blocklotto.raffles.award,\n" + " blocklotto.raffleTypes.maxTickets AS totalParticipations,\n" + " blocklotto.raffleTypes.name,\n" + " blocklotto.raffles.date,\n" + " blocklotto.raffleTypes.info AS information,\n" + " blocklotto.raffleStates.name AS state,\n" + " blocklotto.raffles.winningNumber,\n" + " blocklotto.raffles.blocked\n" + "FROM\n" + " blocklotto.raffles\n" + " INNER JOIN\n" + " blocklotto.raffleTypes ON blocklotto.raffles.type = blocklotto.raffleTypes.id\n" + " INNER JOIN\n" + " blocklotto.raffleStates ON blocklotto.raffles.state = blocklotto.raffleStates.id\n" + "WHERE\n" + " blocklotto.raffleStates.name='Pending'\n" + "ORDER BY blocklotto.raffles.date ASC", wallet.getId()); }

Posteriormente se rellenará el listado de objetos Raffle como se hizo en el punto Listar todos los

sorteos.

7.5.5.14 Lista de los sorteos con participación

Permite al usuario listar todos los sorteos pendientes en los cuales el usuario ha comprado algún

boleto. El usuario tiene que pasar un Json con un campo “id” con el identificador de su cartera.

Únicamente se mostrarán los sorteos en los que se haya realizado alguna compra.

@POST @Path("/listdp") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public List<Raffle> drawsPendingByWalletID(Wallet wallet) { List<Raffle> list = new ArrayList<>(); for (Raffle raffle : new ListRaffles().getUpcomingRaffles (wallet)) { if (raffle.getAmountTicket() > 0) { list.add(raffle); } } return list; }

7.5.5.15 Listar de los sorteos ya celebrados con participación

Permite al usuario listar todos los sorteos ya celebrados en los cuales el usuario haya participado.

El usuario tiene que pasar un Json con un campo “id” con el identificador de su cartera.

@POST @Path("/listpast") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public List<Raffle> pastDrawsByWalletID(Wallet wallet) { List<Raffle> list = new ArrayList<>(); for (Raffle raffle : new ListRaffles().getPastDrawsByWalletID(wallet)) { if (raffle.getAmountTicket() > 0) { list.add(raffle); } } return list; }

Page 70: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

64

Se consultan los sorteos celebrados.

public List<Raffle> getPastDrawsByWalletID(Wallet wallet) { return new MysqlDB().getListRaffles("SELECT \n" + " blocklotto.raffles.id,\n" + " blocklotto.raffleTypes.price,\n" + " blocklotto.raffles.award,\n" + " blocklotto.raffleTypes.maxTickets AS totalParticipations,\n" + " blocklotto.raffleTypes.name,\n" + " blocklotto.raffles.date,\n" + " blocklotto.raffleTypes.info AS information,\n" + " blocklotto.raffleStates.name AS state,\n" + " blocklotto.raffles.winningNumber,\n" + " blocklotto.raffles.blocked\n" + "FROM\n" + " blocklotto.raffles\n" + " INNER JOIN\n" + " blocklotto.raffleTypes ON blocklotto.raffles.type = blocklotto.raffleTypes.id\n" + " INNER JOIN\n" + " blocklotto.raffleStates ON blocklotto.raffles.state = blocklotto.raffleStates.id\n" + "WHERE\n" + " blocklotto.raffleStates.name='Celebrated'\n" + "ORDER BY blocklotto.raffles.date DESC", wallet.getId()); }

7.5.6 Sistema de gestión de sorteos.

Para gestionar los sorteos se hace uso de la libraría Quartz. Esta librería permite programar

eventos que se pueden repetir en el tiempo.

Usos de Quartz en el proyecto:

• Bloqueo del sorteo 15 minutos antes de su celebración. De esta manera no se

podrán comprar más boletos a partir de ese momento.

• Celebración del sorteo al día y hora estipulados con el consecuente pago de

premios. En caso de no haber participantes en un sorteo, este se cancelará.

Creación del nuevo sorteo para dentro de una semana a la misma hora.

• Recuperación de fondos de la cartera maestra el primer día de cada mes a las

5 de la mañana. De esta manera el sistema recupera las ganancias de los

canales abiertos.

7.5.6.1 Quartz Listener

Para el correcto funcionamiento de Quartz se deben establecer lo siguiente:

• JobDetail: El trabajo por realizar desarrollado en una nueva clase.

• Trigger: El lanzador del trabajo al cual se le establecerá una condición de

ejecución dada por un cron compatible con Quartz.

• Scheduler: Un programador que enlaza el JobDetail con el Trigger.

En el código se puede ver que los bloqueos están programados para las 21.45 de los jueves,

viernes, sábados y domingos. Los sorteos se celebrarán para las 22.00 de esos mismos días. Y

por último la recuperación de fondos de la cartera master que se ejecutará a las 05.00 del primer

día de cada mes.

Page 71: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

65

Se debe tener en cuenta que, en la base de datos, en la tabla raffleTypes, se establece el día y la

hora del sorteo. Si coincide el día y hora del sorteo con el lanzamiento de la tarea de celebración

de sorteo, comenzará el procedimiento de sorteo.

Ilustración 35 - Tabla raffleTypes

package com.jorgefernandez.tft.blocklotto.resources.quartz; import org.quartz.*; import org.quartz.ee.servlet.QuartzInitializerListener; import org.quartz.impl.StdSchedulerFactory; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.annotation.WebListener; @WebListener public class QuartzListener extends QuartzInitializerListener { @Override public void contextInitialized(ServletContextEvent sce) { super.contextInitialized(sce); ServletContext ctx = sce.getServletContext(); StdSchedulerFactory factory = (StdSchedulerFactory) ctx.getAttribute(QUARTZ_FACTORY_KEY); try { String cronBlock = "0 45 21 ? * THU,FRI,SAT,SUN *"; String cronDraw = "0 00 22 ? * THU,FRI,SAT,SUN *"; String cronCloseMasterChannel = "0 0 5 1 1/1 ? *"; //String cronBlock = "0 0/1 * 1/1 * ? *"; //String cronDraw = "0 0/1 * 1/1 * ? *"; //String cronCloseMasterChannel = "0 0/1 * 1/1 * ? *"; Scheduler scheduler = factory.getScheduler(); JobKey jobKeyA = new JobKey("startDrawJobDetail", "group1"); JobKey jobKeyB = new JobKey("blockDrawJobDetail", "group1"); JobKey jobKeyC = new JobKey("closeMasterChannelJobDetail", "group1"); JobDetail startDrawJobDetail = JobBuilder.newJob(StartDrawJob.class).withIdentity(jobKeyA).build(); JobDetail blockDrawJobDetail = JobBuilder.newJob(BlockDrawJob.class).withIdentity(jobKeyB).build(); JobDetail closeMasterChannelJobDetail = JobBuilder.newJob(CloseMasterChannelJob.class).withIdentity(jobKeyC).build(); Trigger startDrawTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule( CronScheduleBuilder.cronSchedule(cronDraw)).startNow().build(); Trigger blockDrawTrigger = TriggerBuilder.newTrigger().withIdentity("trigger2", "group1").withSchedule( CronScheduleBuilder.cronSchedule(cronBlock)).startNow().build(); Trigger closeMasterChannelTrigger = TriggerBuilder.newTrigger().withIdentity("trigger3", "group1").withSchedule( CronScheduleBuilder.cronSchedule(cronCloseMasterChannel)).startNow().build(); scheduler.start(); scheduler.scheduleJob(startDrawJobDetail, startDrawTrigger); scheduler.scheduleJob(blockDrawJobDetail, blockDrawTrigger); scheduler.scheduleJob(closeMasterChannelJobDetail, closeMasterChannelTrigger); } catch (Exception e) { ctx.log("There was an error scheduling the job.", e); } } }

Page 72: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

66

7.5.6.2 BlockDrawListener

Tarea que bloquea el sorteo 15 minutos antes de su celebración.

package com.jorgefernandez.tft.blocklotto.resources.quartz; import com.jorgefernandez.tft.blocklotto.resources.bbdd.MysqlDB; import com.jorgefernandez.tft.blocklotto.resources.tools.Tools; import org.quartz.Job; import org.quartz.JobExecutionContext; import java.util.Calendar; import java.util.Date; public class BlockDrawJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); int i = Tools.getRaffleByDayAndHour(calendar); if (i != 0) { new MysqlDB().setRaffleBlocked(i); } } }

Se comprueba que exista un sorteo programado para este día y esta hora. De ser así se devuelve

el identificador del sorteo.

public static int getRaffleByDayAndHour(Calendar calendar) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH"); simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); return new MysqlDB().getRaffleByDayAndHour(calendar.get(Calendar.DAY_OF_WEEK), Integer.valueOf(simpleDateFormat.format(calendar.getTime()))); }

public int getRaffleByDayAndHour(int day, int hour) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT a.id " + "FROM blocklotto.raffles as a " + "INNER JOIN blocklotto.raffleTypes as b " + "WHERE a.type=b.id " + "AND (b.day=? AND b.hour=?) " + "AND a.state=1 " + "ORDER BY a.id ASC " + "limit 1"); p.setInt(1, day); p.setInt(2, hour); p.executeQuery(); ResultSet rs = p.getResultSet(); if (rs.next()) { return rs.getInt("id"); } rs.close(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return 0; }

Page 73: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

67

Por último, se establece como bloqueado ese sorteo.

public void setRaffleBlocked(int idRaffle) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("UPDATE blocklotto.raffles " + "SET blocklotto.raffles.blocked=1 " + "WHERE blocklotto.raffles.id=?"); p.setInt(1, idRaffle); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

7.5.6.3 StartDrawJob

Tarea que inicia el procedimiento de sorteo y creación del sorteo del mismo tipo para la

siguiente semana.

Se realiza la comprobación de que exista un sorteo para ese día y esa hora.

package com.jorgefernandez.tft.blocklotto.resources.quartz; import com.jorgefernandez.tft.blocklotto.resources.raffles.ManageRaffles; import com.jorgefernandez.tft.blocklotto.resources.tools.Tools; import org.quartz.Job; import org.quartz.JobExecutionContext; import java.util.Calendar; import java.util.Date; public class StartDrawJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); int i = Tools.getRaffleByDayAndHour(calendar); if (i != 0) { new ManageRaffles().celebrateDrawAndCreateOtherOneSameType(i, calendar); } } }

public void celebrateDrawAndCreateOtherOneSameType(int idRaffle, Calendar calendar) { MysqlDB mysqlDB = new MysqlDB(); String[] winner = startDraw(idRaffle); if (!winner[1].isEmpty()) { payPrize(winner[1], idRaffle); mysqlDB.addNotification(winner[1], idRaffle); } else { mysqlDB.setRaffleCanceled(idRaffle); } createRaffle(mysqlDB.getTypeByRaffleID(idRaffle), getDateForFutureRaffle(calendar)); }

Comienza el procedimiento de realización del sorteo.

public String[] startDraw(int idRaffle) { Random generator = new Random(); MysqlDB mysqlDB = new MysqlDB(); HashMap<String, String> ticketsList = mysqlDB.getTicketsList(idRaffle); String[] winner = {"", ""}; if (ticketsList.size() > 0) { Object[] keys = ticketsList.keySet().toArray(); Object[] values = ticketsList.values().toArray(); int random = generator.nextInt(keys.length); winner[0] = keys[random].toString(); winner[1] = values[random].toString(); mysqlDB.addRaffleWinner(idRaffle, winner[0]); } return winner; }

Page 74: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

68

Se obtienen los boletos participantes junto con sus dueños.

public HashMap<String, String> getTicketsList(int idRaffle) { HashMap<String, String> ticketsList = new HashMap<>(); try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.raffleNumbers.codWallet, blocklotto.raffleNumbers.number " + "FROM blocklotto.raffleNumbers " + "WHERE blocklotto.raffleNumbers.codRaffle =?"); p.setInt(1, idRaffle); p.executeQuery(); ResultSet rs = p.getResultSet(); while (rs.next()) { ticketsList.put(rs.getString("number"), rs.getString("codWallet")); } rs.close(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return ticketsList; }

Se añade el ganador del sorteo al sistema.

public void addRaffleWinner(int idRaffle, String prizeTicket) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("UPDATE blocklotto.raffles " + "SET blocklotto.raffles.winningNumber =?, " + " blocklotto.raffles.state = 2 " + "WHERE " + " blocklotto.raffles.id =?"); p.setString(1, prizeTicket); p.setInt(2, idRaffle); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

Se paga el premio y acto seguido se cierra el canal para que el importe del premio aparezca en

el saldo de la cartera ganadora.

public void payPrize(String codWallet, int idRaffle) { if (!codWallet.isEmpty()) { MockLightningAccessor mockLightning = new MockLightningAccessor(); Invoice invoice = mockLightning.createInvoice(codWallet, new MysqlDB().getPrizeRaffle(idRaffle)); mockLightning.closeChannel(mockLightning.sendPaymentWithPayReq(invoice.getPay_req(), masterWallet, "Pago de premio")); } }

Se añade la notificación de ganador del sorteo.

public void addNotification(String codWallet, int codRaffle) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("INSERT INTO blocklotto.notifications(codWallet,codRaffle) " + "VALUES(?,?)"); p.setString(1, codWallet); p.setInt(2, codRaffle); p.execute(); } } catch (SQLException e) { e.printStackTrace(); } }

Page 75: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

69

En caso de no existir participantes, se cancela el sorteo.

public void setRaffleCanceled(int idRaffle) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("UPDATE blocklotto.raffles " + "SET blocklotto.raffles.state=3 " + "WHERE blocklotto.raffles.id=?"); p.setInt(1, idRaffle); p.execute(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } }

public int getTypeByRaffleID(int idRaffle) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.raffles.type " + "FROM blocklotto.raffles " + "WHERE blocklotto.raffles.id=?"); p.setInt(1, idRaffle); p.executeQuery(); ResultSet rs = p.getResultSet(); if (rs.next()) { return rs.getInt("type"); } rs.close(); p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return 0; }

Se calcula el día del siguiente sorteo.

public String getDateForFutureRaffle(Calendar calendar) { calendar.add(Calendar.DAY_OF_YEAR, 7); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:00"); simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); return simpleDateFormat.format(calendar.getTime()); }

Una vez recabados los datos del tipo de sorteo a crear y el día de celebración, se crea el sorteo.

public static int createRaffle(int type, String date) { return new MysqlDB().addRaffle(type, date); }

public int addRaffle(int type, String date) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("INSERT INTO blocklotto.raffles(date,type,award) " + "VALUES(?,?,?)", Statement.RETURN_GENERATED_KEYS); p.setString(1, date); p.setInt(2, type); p.setFloat(3, getInitialPrizeByRaffleID(type)); p.executeUpdate(); ResultSet rs = p.getGeneratedKeys(); int key = 0; if (rs.next()) { key = rs.getInt(1); } p.close(); connection.close(); return key; } } catch (SQLException ignore) { } return 0; }

Page 76: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

70

A la hora de crear el sorteo se establece el premio de forma dinámica según el tipo de sorteo.

Concretamente el premio base son cinco veces el precio de un boleto. Dependiendo del tipo de

sorteo, el premio base cambiará ya que el precio de los boletos difiere de uno a otro.

public long getInitialPrizeByRaffleID(int type) { try { Connection connection = connection(); if (connection != null) { PreparedStatement p = connection.prepareStatement("SELECT blocklotto.raffleTypes.price " + "FROM blocklotto.raffleTypes " + "WHERE blocklotto.raffleTypes.id=?"); p.setInt(1, type); p.executeQuery(); ResultSet rs = p.getResultSet(); if (rs.next()) { return Math.round(5L * rs.getLong("price")); } p.close(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } return 0L; }

7.5.6.4 CloseMasterChannelJob

Tarea que cierra todos los canales abiertos de la cartera master para la recuperación de fondos.

Se puede observar el funcionamiento de la extracción de fondos en el punto Recuperar saldo de

los canales abiertos .

package com.jorgefernandez.tft.blocklotto.resources.quartz; import com.jorgefernandez.tft.blocklotto.resources.lightning.MockLightningAccessor; import com.jorgefernandez.tft.blocklotto.resources.tools.Configuration; import org.quartz.Job; import org.quartz.JobExecutionContext; public class CloseMasterChannelJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) { Configuration configuration = Configuration.getInstance(); MockLightningAccessor mockLightning = new MockLightningAccessor(); mockLightning.withdrawFunds(configuration.masterWallet); } }

7.5.7 TDD

Para el desarrollo de este proyecto me he ayudado del desarrollo guiado por pruebas. A

continuación, el código de todas las pruebas creadas.

Page 77: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

71

7.5.7.1 ManageRaffleTest package com.jorgefernandez.tft.blocklotto.resources.raffles; import com.jorgefernandez.tft.blocklotto.resources.bbdd.MysqlDB; import com.jorgefernandez.tft.blocklotto.resources.lightning.MockLightningAccessor; import com.jorgefernandez.tft.blocklotto.resources.lightning.objects.BuyRaffle; import com.jorgefernandez.tft.blocklotto.resources.lightning.objects.Wallet; import com.jorgefernandez.tft.blocklotto.resources.tools.Tools; import org.junit.Assert; import org.junit.Test; import java.util.Calendar; import java.util.GregorianCalendar; public class ManageRafflesTest { public int createRaffle() { return ManageRaffles.createRaffle(4, Tools.getCurrentTime()); } @Test public void createRaffle_Created_RightParameters() { int id = ManageRaffles.createRaffle(3, Tools.getCurrentTime()); Assert.assertNotEquals(0, id); new ManageRaffles().removeRaffle(id); } @Test public void createRaffle_NotCreated_WrongParameters() { int id = ManageRaffles.createRaffle(9, Tools.getCurrentTime()); Assert.assertEquals(0, id); } @Test public void removeRaffle_Removed_RaffleExists() { int id = createRaffle(); Assert.assertTrue(new ManageRaffles().removeRaffle(id)); } @Test public void removeRaffle_NotRemoved_RaffleDoesntExist() { int id = -1; Assert.assertFalse(new ManageRaffles().removeRaffle(id)); } @Test public void getAwardRaffle_Award_RaffleExists() { int id = createRaffle(); MysqlDB mysqlDB = new MysqlDB(); Assert.assertEquals(2500000, mysqlDB.getPrizeRaffle(id)); new ManageRaffles().removeRaffle(id); } @Test public void getAwardRaffle_0_RaffleDoesntExist() { Assert.assertEquals(0, new MysqlDB().getPrizeRaffle(-1)); } @Test public void getRemainingTickets_NumberTickets_RaffleExists() { int id = createRaffle(); Assert.assertEquals(250, new MysqlDB().getRemainingTickets(id)); new ManageRaffles().removeRaffle(id); } @Test public void getRemainingTickets_0_RaffleDoesntExists() { Assert.assertEquals(0, new MysqlDB().getRemainingTickets(-1)); } @Test public void buyTickets_245_WithStock() { checkBuyTickets(5, 245); } @Test public void buyTickets_250_WithOutStock() { checkBuyTickets(300, 250); }

Page 78: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

72

private void checkBuyTickets(int i, int i2) { int id = createRaffle(); Wallet wallet = createWallet(); ManageRaffles manageRaffles = new ManageRaffles(); MysqlDB mysqlDB = new MysqlDB(); BuyRaffle buyRaffle = new BuyRaffle(wallet.getId(), id, i); manageRaffles.buyTickets(buyRaffle); Assert.assertEquals(i2, mysqlDB.getRemainingTickets(id)); mysqlDB.deleteTickets(id); manageRaffles.removeRaffle(id); new MockLightningAccessor().deleteWallet(wallet); } @Test public void startDraw_Raffled_TicketsBuyed() { int id = createRaffle(); Wallet wallet = createWallet(); ManageRaffles manageRaffles = new ManageRaffles(); BuyRaffle buyRaffle = new BuyRaffle(wallet.getId(), id, 5); manageRaffles.buyTickets(buyRaffle); Assert.assertEquals(5, manageRaffles.startDraw(id)[0].length()); manageRaffles.removeRaffle(id); new MockLightningAccessor().deleteWallet(wallet); } @Test public void startDraw_NotRaffled_TicketsDindtBuy() { int id = createRaffle(); ManageRaffles manageRaffles = new ManageRaffles(); Assert.assertEquals(0, manageRaffles.startDraw(id)[0].length()); manageRaffles.removeRaffle(id); } @Test public void payPrize_Paid_RaffleDrawn() { ManageRaffles manageRaffles = new ManageRaffles(); MysqlDB mysqlDB = new MysqlDB(); Wallet wallet = createWallet(); int id = createRaffle(); BuyRaffle buyRaffle = new BuyRaffle(wallet.getId(), id, 5); manageRaffles.buyTickets(buyRaffle); manageRaffles.payPrize(manageRaffles.startDraw(id)[1], id); Assert.assertEquals((99465950 + mysqlDB.getInitialPrizeByRaffleID(4)), Tools.convertBTCtoSatoshis(mysqlDB.getAmountByWalletID(wallet.getId()))); manageRaffles.removeRaffle(id); new MockLightningAccessor().deleteWallet(wallet); } private Wallet createWallet() { Wallet wallet = new Wallet(); wallet.setPass("kokokoko"); return new MockLightningAccessor().createWallet(wallet); } @Test public void getDateForFutureRaffle_17_calendar() { Calendar calendar = new GregorianCalendar(2018,0,1); int i = calendar.get(Calendar.DAY_OF_MONTH); new ManageRaffles().getDateForFutureRaffle(calendar); Assert.assertEquals(i + 7, calendar.get(Calendar.DAY_OF_MONTH)); }

Page 79: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

73

7.5.7.2 MockLightningAccessorTest package com.jorgefernandez.tft.blocklotto.resources.lightning; import com.jorgefernandez.tft.blocklotto.resources.bbdd.MysqlDB; import com.jorgefernandez.tft.blocklotto.resources.lightning.objects.*; import com.jorgefernandez.tft.blocklotto.resources.tools.Tools; import org.junit.Assert; import org.junit.Test; import java.util.ArrayList; import java.util.List; import static com.jorgefernandez.tft.blocklotto.resources.tools.Tools.*; public class MockLightningAccessorTest { @Test public void generatedRandomWords() { Assert.assertEquals(24, new MockLightningAccessor().generateRandomWords().size()); } @Test public void createWallet_Created_WithPass() { Wallet wallet = createWallet("kokokoko"); Assert.assertEquals(66, wallet.getPub().length()); Assert.assertEquals(34, wallet.getAddress().length()); Assert.assertEquals(24, wallet.getSeedWords().size()); Assert.assertNotNull(wallet.getId()); new MockLightningAccessor().deleteWallet(wallet); } @Test public void createWallet_NotCreated_WithOutPass() { Wallet wallet = createWallet(""); Assert.assertNull(wallet.getId()); Assert.assertNull(wallet.getPub()); Assert.assertNull(wallet.getAddress()); Assert.assertNull(wallet.getSeedWords()); } private Wallet unlockWallet(String pass) { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet wallet = createWallet("kokokoko"); Wallet walletB = new Wallet(); walletB.setPass(pass); walletB.setId(wallet.getId()); wallet = mockLightning.unlockWallet(walletB); mockLightning.deleteWallet(wallet); return wallet; } @Test public void unlockWallet_Unlocked_RightPass() { Assert.assertTrue(unlockWallet("kokokoko").isUnlock()); } @Test public void unlockWallet_Locked_WrongPass() { Assert.assertFalse(unlockWallet("aaa").isUnlock()); } @Test public void restoreWallet_Restored_RightWords() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = new Wallet(); walletB.setSeedWords(walletA.getSeedWords()); walletB.setPass("kukukuku"); Assert.assertEquals(walletA.getId(), mockLightning.restoreWallet(walletB).getId()); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void restoreWallet_Fail_WrongWords() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = new Wallet(); walletB.setSeedWords(stringToWords("car hello monitor telephone door airplane train boat clock headphone speaker")); walletB.setPass("kukukuku"); Assert.assertNull(mockLightning.restoreWallet(walletB).getId()); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void deleteWallet_Deleted_WalletCreated() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet wallet = createWallet("kokokoko"); Assert.assertTrue(mockLightning.deleteWallet(wallet)); } @Test public void deleteWallet_NotDeleted_WalletCreated() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet wallet = createWallet(""); Assert.assertFalse(mockLightning.deleteWallet(wallet)); }

Page 80: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

74

@Test public void deleteChannel_NotDeleted_ChannelCreated() { Assert.assertFalse(new MysqlDB().deleteChannel("TEST")); } @Test public void deleteChannel_Deleted_ChannelCreated() { MockLightningAccessor mockLightningAccessor = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); mockLightningAccessor.createPeer(walletA.getId(), walletB.getId()); Channel channel = mockLightningAccessor.openChannel(walletA.getId(), walletB.getId(), 20000, 0); Assert.assertTrue(new MysqlDB().deleteChannel(channel.getFunding_txid())); mockLightningAccessor.deleteWallet(walletA); mockLightningAccessor.deleteWallet(walletB); } @Test public void getWalletBalance_1Balance_RightWallet() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet wallet = createWallet("kokokoko"); WalletBalance walletBalance = mockLightning.getWalletBalance(wallet.getId()); Assert.assertEquals(1f, walletBalance.getTotal_balance(), 0); mockLightning.deleteWallet(wallet); } @Test public void getWalletBalance_0Balance_WrongWallet() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet wallet = createWallet(""); WalletBalance walletBalance = mockLightning.getWalletBalance(wallet.getId()); Assert.assertEquals(0f, walletBalance.getTotal_balance(), 0); mockLightning.deleteWallet(wallet); } @Test public void createPeer_Created_TwoDifferentWallets() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet nodeA = createWallet("kokokoko"); Wallet nodeB = createWallet("kokokoko"); mockLightning.createPeer(nodeA.getId(), nodeB.getId()); Assert.assertTrue(new MysqlDB().checkPeer(nodeA.getId(), nodeB.getId())); mockLightning.deleteWallet(nodeA); mockLightning.deleteWallet(nodeB); } @Test public void createPeer_NotCreated_TwoSameWallet() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet nodeA = createWallet("kokokoko"); mockLightning.createPeer(nodeA.getId(), nodeA.getId()); Assert.assertFalse(new MysqlDB().checkPeer(nodeA.getId(), nodeA.getId())); mockLightning.deleteWallet(nodeA); } @Test public void createPeer_NotCreated_PeerExist() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet nodeA = createWallet("kokokoko"); Wallet nodeB = createWallet("kokokoko"); mockLightning.createPeer(nodeA.getId(), nodeB.getId()); Assert.assertFalse(mockLightning.createPeer(nodeA.getId(), nodeB.getId())); mockLightning.deleteWallet(nodeA); mockLightning.deleteWallet(nodeB); } @Test public void deletePeer_Deleted_PeerExist() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet nodeA = createWallet("kokokoko"); Wallet nodeB = createWallet("kokokoko"); mockLightning.createPeer(nodeA.getId(), nodeB.getId()); Assert.assertTrue(mockLightning.deletePeer(nodeA.getId(), nodeB.getId())); mockLightning.deleteWallet(nodeA); mockLightning.deleteWallet(nodeB); } @Test public void deletePeer_NotDeleted_PeerNotExist() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet nodeA = createWallet("kokokoko"); Wallet nodeB = createWallet("kokokoko"); Assert.assertFalse(mockLightning.deletePeer(nodeA.getId(), nodeB.getId())); mockLightning.deleteWallet(nodeA); mockLightning.deleteWallet(nodeB); } private Wallet createWallet(String pass) { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet wallet = new Wallet(); wallet.setPass(pass); return mockLightning.createWallet(wallet); }

Page 81: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

75

@Test public void convertBTCtoSatoshi_Converted_DiferentTests() { Assert.assertEquals(0L, convertBTCtoSatoshis(0d)); Assert.assertEquals(100000000L, convertBTCtoSatoshis(1d)); Assert.assertEquals(84000L, convertBTCtoSatoshis(0.00084000)); Assert.assertEquals(311234000L, convertBTCtoSatoshis(3.11234000)); } @Test public void convertSatoshitoBTC_Converted_DiferentTests() { Assert.assertEquals(0d, convertSatoshistoBTC(0), 0); Assert.assertEquals(1d, convertSatoshistoBTC(100000000), 0); Assert.assertEquals(0.00000840d, convertSatoshistoBTC(840), 0); Assert.assertEquals(2.08778004, convertSatoshistoBTC(208778004), 0); } @Test public void openChannel_DontOpen_WithOutPeerConnection() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletLocal = createWallet("kokokoko"); Wallet walletRemote = createWallet("kokokoko"); String s = mockLightning.openChannel(walletLocal.getId(), walletRemote.getId(), 50000, 0).getFunding_txid(); Assert.assertNull(s); mockLightning.deleteWallet(walletLocal); mockLightning.deleteWallet(walletRemote); } @Test public void openChannel_Openend_WithPeerConnection() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletLocal = createWallet("kokokoko"); Wallet walletRemote = createWallet("kokokoko"); mockLightning.createPeer(walletLocal.getId(), walletRemote.getId()); String s = mockLightning.openChannel(walletLocal.getId(), walletRemote.getId(), 50000, 0).getFunding_txid(); Assert.assertEquals(64, s.length()); mockLightning.deletePeer(walletLocal.getId(), walletRemote.getId()); new MysqlDB().deleteChannel(s); mockLightning.deleteWallet(walletLocal); mockLightning.deleteWallet(walletRemote); } @Test public void generateRandomStrings_Generated_DifferentTests() { Assert.assertEquals(50, generateRandomString(50).length()); Assert.assertEquals(80, generateRandomString(80).length()); Assert.assertEquals(189, generateRandomString(189).length()); Assert.assertEquals(1, generateRandomString(1).length()); Assert.assertEquals(0, generateRandomString(0).length()); } @Test public void createInvoice_Added_RightParameters() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet wallet = createWallet("kokokoko"); Invoice invoiceA = mockLightning.createInvoice(wallet.getId(), 1000); Invoice invoiceB = mockLightning.createInvoice(wallet.getId(), 1000); Assert.assertEquals(189, invoiceA.getPay_req().length()); Assert.assertEquals(2, invoiceB.getAdd_index()); mockLightning.deleteWallet(wallet); } @Test public void createInvoice_NotAdded_WrongParameters() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet wallet = createWallet("kokoko"); Invoice invoiceA = mockLightning.createInvoice(wallet.getId(), 1000); Invoice invoiceB = mockLightning.createInvoice(wallet.getId(), 1000); Assert.assertNull(invoiceA.getPay_req()); Assert.assertEquals(0, invoiceB.getAdd_index()); } @Test public void getValidPaymentRoute_Valid_RightParameters() { MockLightningAccessor mockLightning = new MockLightningAccessor(); MysqlDB mysqlDB = new MysqlDB(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); mockLightning.createPeer(walletA.getId(), walletB.getId()); mockLightning.openChannel(walletA.getId(), walletB.getId(), 32000, 0); Invoice invoice = mockLightning.createInvoice(walletB.getId(), 10000); Assert.assertEquals(64, mysqlDB.getValidPaymentRoute(invoice.getPay_req(), walletA.getId(), walletB.getId()).length()); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); }

Page 82: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

76

@Test public void getValidPaymentRoute_Invalid_WrongParameters() { MockLightningAccessor mockLightning = new MockLightningAccessor(); MysqlDB mysqlDB = new MysqlDB(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); Wallet walletC = createWallet("kokokoko"); mockLightning.createPeer(walletA.getId(), walletB.getId()); mockLightning.openChannel(walletA.getId(), walletB.getId(), 32000, 0); Invoice invoice = mockLightning.createInvoice(walletB.getId(), 10000); Assert.assertEquals("", mysqlDB.getValidPaymentRoute(invoice.getPay_req(), walletC.getId(), walletB.getId())); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); mockLightning.deleteWallet(walletC); } @Test public void sendPaymentWithPayReq_Send_HaveFunds() { MockLightningAccessor mockLightning = new MockLightningAccessor(); MysqlDB mysqlDB = new MysqlDB(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); int amount = 1000000; Invoice invoice = mockLightning.createInvoice(walletB.getId(), amount); mockLightning.closeChannel(mockLightning.sendPaymentWithPayReq(invoice.getPay_req(), walletA.getId(), "Testing SendPayments")); Assert.assertEquals(1.01D, mysqlDB.getAmountByWalletID(walletB.getId()), 0); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void sendPaymentWithPayReq_DontSend_HaventFunds() { MockLightningAccessor mockLightning = new MockLightningAccessor(); MysqlDB mysqlDB = new MysqlDB(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); int amount = 1000000000; Invoice invoice = mockLightning.createInvoice(walletB.getId(), amount); mockLightning.closeChannel(mockLightning.sendPaymentWithPayReq(invoice.getPay_req(), walletA.getId(), "Testing SendPayments")); Assert.assertEquals(1f, mysqlDB.getAmountByWalletID(walletB.getId()), 0); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void sendPaymentWithPayReq_0Payments_OutOfBalance() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); Invoice invoice = mockLightning.createInvoice(walletB.getId(), 500000000); mockLightning.sendPaymentWithPayReq(invoice.getPay_req(), walletA.getId(), "Testing paymentMoves"); Assert.assertEquals(100000000L, convertBTCtoSatoshis(mockLightning.getWalletBalance(walletA.getId()).getTotal_balance())); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void sendPaymentWithPayReq_1Payment_HaveEnoughBalance() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); Invoice invoice = mockLightning.createInvoice(walletB.getId(), 500000); mockLightning.sendPaymentWithPayReq(invoice.getPay_req(), walletA.getId(), "Testing paymentMoves"); Assert.assertEquals(98000000L, convertBTCtoSatoshis(mockLightning.getWalletBalance(walletA.getId()).getTotal_balance())); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void wordsToString_valid_RightParameters() { List<String> list = new ArrayList<>(); list.add("dog"); list.add("cat"); list.add("lion"); Assert.assertEquals(getHashText("dog cat lion"), Tools.wordsToString(list)); } @Test public void stringToWords_valid_RightParameters() { List<String> list = new ArrayList<>(); list.add("dog"); list.add("cat"); list.add("lion"); Assert.assertEquals(list, Tools.stringToWords("dog cat lion")); }

Page 83: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

77

@Test public void getTotalBalanceInChannels_TotalBalance_ExistChannelForWallet() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); Invoice invoice = mockLightning.createInvoice(walletB.getId(), 50000); mockLightning.sendPaymentWithPayReq(invoice.getPay_req(), walletA.getId(), "Testing TotalBalanceInChannels"); invoice = mockLightning.createInvoice(walletA.getId(), 1000000); mockLightning.sendPaymentWithPayReq(invoice.getPay_req(), walletB.getId(), "Testing TotalBalanceInChannels"); Assert.assertEquals(1040950, mockLightning.getTotalBalanceInChannels(walletB).getBalance()); Assert.assertEquals(2940950, mockLightning.getTotalBalanceInChannels(walletA).getBalance()); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void getTotalBalanceInChannels_0_DontExistChannelForWallet() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); Assert.assertEquals(0, mockLightning.getTotalBalanceInChannels(walletB).getBalance()); Assert.assertEquals(0, mockLightning.getTotalBalanceInChannels(walletA).getBalance()); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void getAllPaymentMovesByWallet_Payments_ExistMovements() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); Invoice invoice = mockLightning.createInvoice(walletB.getId(), 50000); mockLightning.sendPaymentWithPayReq(invoice.getPay_req(), walletA.getId(), "Testing paymentMoves"); invoice = mockLightning.createInvoice(walletA.getId(), 1000000); mockLightning.sendPaymentWithPayReq(invoice.getPay_req(), walletB.getId(), "Testing paymentMoves"); invoice = mockLightning.createInvoice(walletB.getId(), 10000); mockLightning.sendPaymentWithPayReq(invoice.getPay_req(), walletA.getId(), "Testing paymentMoves"); List<PaymentMoves> paymentMoves = mockLightning.getAllPaymentMovesByWallet(walletA); Assert.assertEquals(100950000L, paymentMoves.get(1).getHistoricalAmount()); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void getAllPaymentMovesByWallet_0_DontExistMovements() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); List<PaymentMoves> paymentMoves = mockLightning.getAllPaymentMovesByWallet(walletA); Assert.assertEquals(0, paymentMoves.size()); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void moneyTransfer_Error_SameWallet() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Assert.assertEquals("Error", mockLightning.transferCoin(walletA.getId(), new MysqlDB().getWalletIDByPUB(walletA.getPub()), 800000).getMessage()); mockLightning.deleteWallet(walletA); } @Test public void transferCoin_TransferComplete_WalletAHasFundsAndTransferToWalletBInNewChannel() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); Assert.assertEquals("Transfer complete", mockLightning.transferCoin(walletA.getId(), new MysqlDB().getWalletIDByPUB(walletB.getPub()), 800000).getMessage()); Assert.assertEquals(1, new MysqlDB().getNumberChannelsbyWallet(walletB.getId())); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void transferCoin_Error_WalletAHasNotFundsAndTransferToWalletBInNewChannel() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); Assert.assertEquals("Error", mockLightning.transferCoin(walletA.getId(), new MysqlDB().getWalletIDByPUB(walletB.getPub()), 800000000).getMessage()); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); }

Page 84: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

78

@Test public void transferCoin_TransferComplete_WalletAHasFundsAndTransferToWalletBInExistingChannel() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); mockLightning.createPeer(walletA.getId(), walletB.getId()); mockLightning.openChannel(walletA.getId(), walletB.getId(), 1000000, 0); Assert.assertEquals("Transfer complete", mockLightning.transferCoin(walletA.getId(), new MysqlDB().getWalletIDByPUB(walletB.getPub()), 800000).getMessage()); Assert.assertEquals(800000, mockLightning.getTotalBalanceInChannels(walletB).getBalance()); Assert.assertEquals(1, new MysqlDB().getNumberChannelsbyWallet(walletB.getId())); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); } @Test public void transferCoin_TransferComplete_WalletAHasFundsAndTransferToWalletBThroughWalletCInExistingChannel() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); Wallet walletC = createWallet("kokokoko"); mockLightning.createPeer(walletA.getId(), walletC.getId()); mockLightning.openChannel(walletA.getId(), walletC.getId(), 1000000, 0); mockLightning.createPeer(walletC.getId(), walletB.getId()); mockLightning.openChannel(walletC.getId(), walletB.getId(), 1000000, 0); Assert.assertEquals("Transfer complete", mockLightning.transferCoin(walletA.getId(), new MysqlDB().getWalletIDByPUB(walletB.getPub()), 800000).getMessage()); Assert.assertEquals(800000, mockLightning.getTotalBalanceInChannels(walletB).getBalance()); Assert.assertEquals(1, new MysqlDB().getNumberChannelsbyWallet(walletB.getId())); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); mockLightning.deleteWallet(walletC); } @Test public void transferCoin_TransferComplete_WalletAHasFundsAndTransferToWalletBThroughWalletCInNewChannel() { MockLightningAccessor mockLightning = new MockLightningAccessor(); Wallet walletA = createWallet("kokokoko"); Wallet walletB = createWallet("kokokoko"); Wallet walletC = createWallet("kokokoko"); mockLightning.createPeer(walletA.getId(), walletC.getId()); mockLightning.openChannel(walletA.getId(), walletC.getId(), 1000000, 0); mockLightning.createPeer(walletC.getId(), walletB.getId()); mockLightning.openChannel(walletC.getId(), walletB.getId(), 100000, 0); Assert.assertEquals("Transfer complete", mockLightning.transferCoin(walletA.getId(), new MysqlDB().getWalletIDByPUB(walletB.getPub()), 800000).getMessage()); Assert.assertEquals(800000, mockLightning.getTotalBalanceInChannels(walletB).getBalance()); Assert.assertEquals(2, new MysqlDB().getNumberChannelsbyWallet(walletB.getId())); mockLightning.deleteWallet(walletA); mockLightning.deleteWallet(walletB); mockLightning.deleteWallet(walletC); } }

8. Conclusiones y trabajos futuros En este apartado se expondrá cual ha sido el resultado final, así como si se han cumplido o no

los objetivos. Por último, se expondrán las posibles mejoras que se le podría aplicar al proyecto

en un futuro.

8.1 Resultado Al terminar este proyecto se ha obtenido un servicio web el cual es capaz de suministrar

información a un cliente mediante diferentes peticiones de este. Este servicio web es capaz de

simular operaciones propias de Lightning Network, como son:

• Creación, restauración y desbloqueo de una cartera.

• Realización de pagos instantáneos a través de los canales.

• Consulta de saldo tanto de la cartera como de los canales abiertos en los que la cartera esté

incluida.

• Cierre de estos canales para recuperar los fondos que permanecen dentro de los canales

abiertos.

• Transferencias eligiendo las rutas válidas más cortas. Estas rutas contienen canales de los

cuales no formamos parte.

• Listar notificaciones que avisan al ganador de un sorteo.

Page 85: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

79

• Listar los sorteos, totales, pendientes, pendientes con participación y los celebrados.

Por otro lado, también se ha desarrollado el sistema automatizado de sorteos que celebra, paga

premios y crea nuevos sorteos.

8.2 Consecución de los objetivos Si bien todos los casos de uso han sido cumplidos satisfactoriamente, también es verdad que no

se ha hecho uso de la tecnología Lightning Network. Esto ha sido así por lo ya explicado en el

apartado 3.3 Problemas con Lightning Network. Personalmente me hubiera gustado que el

protocolo hubiera estado más avanzado y no diera tantos problemas a la hora de desarrollar

con él en Java. Como se ha comentado anteriormente, la búsqueda de soluciones para el

lenguaje Java de dicho protocolo son frustrantes. Por ejemplo, si nos fijamos en el número de

usos de librerías como LightningJ en Maven Repository, vemos que no lo está usando

prácticamente nadie. Muchos desarrolladores optan por realizar sus proyectos en Python o en

JavaScript ya que la creadora del proyecto, Lightning Network Daemon, da soporte a esos

lenguajes con tutoriales y diferentes guías. Así y todo, Lightning Network Daemon está en una

fase muy temprana.

Ilustración 36 - Maven Repository - LightningJ

8.3 Trabajos futuros A continuación, se expondrán cuáles podrían ser algunas futuras líneas de trabajo relacionadas

con este proyecto:

• Una vez se estabilice el desarrollo de Lightning Network, habría que rehacer el proyecto para

que fuera compatible con el protocolo.

• Añadir un sistema de control de saldo a la cartera maestra, para que, de esta manera, si el

saldo fuera inferior a una cierta cantidad, se cerraran los canales relacionados con la cartera

y de este modo se recuperara liquidez para poder hacer frente a los premios.

• Añadir una interfaz de administración del sistema. Esta interfaz podría dar información

como número de usuarios, cantidad recaudada en diferentes periodos de tiempo,

estadísticas sobre el juego, etc.

• Desarrollo de una interfaz web para poder hacer uso de la aplicación desde cualquier

dispositivo.

Page 86: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

80

9. Herramientas utilizadas A continuación, los recursos necesarios para la realización de este proyecto.

9.1 Hardware

9.1.1 Ordenador portátil personal

Para el desarrollo del proyecto he hecho uso de mi ordenador portátil cuyas especificaciones

son las siguientes:

• Intel® Core™ i7-4700MQ CPU @2.40GHz.

• 8 GB de RAM

• Tarjeta gráfica Nvidia GTX 770M 3GB DDR5

• Conexión a internet

9.1.2 Servidores

Los servidores para ofrecer el servicio están documentados en el apartado Diagrama de

despliegue.

9.2 Software

9.2.1 Windows 10 Home

Este es el sistema operativo sobre el que desarrollo en mi ordenador portátil personal. Con

licencia personal de estudiante.

9.2.2 IntelliJ IDEA Ultimate 2018.3

Para el desarrollo en Java se hace uso de este entorno de desarrollo. Licencia personal de

estudiante.

9.2.3 Trello

Este software de administración de tareas se ha usado para llevar el control de las tareas

vinculadas a este proyecto. Permite la creación de listas de tareas y el establecimiento de colores

para marcarlas como realizadas, pendientes o en proceso. Comparto Trello con mi compañera

de proyecto Cynthia J. Afonso García. De esta manera estamos siempre informados de en qué

se está trabajando en cada momento.

9.2.4 SoapUI by SmartBear

Herramienta que permite la realización de pruebas contra servidores web. Lo utilizo para probar

las peticiones enviadas al web service mandando los parámetros con Json.

9.2.5 Github

Permite el alojamiento de proyectos utilizando el sistema de control de versiones. Este proyecto

está alojado en esta dirección https://github.com/kovutech/BlockLotto.

9.2.6 MySQL Workbench

Herramienta de diseño de bases de datos Mysql.

9.2.7 Github Desktop

Herramienta que facilita la gestión del repositorio Github.

Page 87: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

81

10. Referencias [1] ¿Qué es la tecnología de contabilidad distribuida o blockchain? -

https://www.criptonoticias.com/informacion/que-es-tecnologia-contabilidad-distribuida-

blockchain/

[2] ¿Qué es la minería de bitcoins (criptomonedas)? -

https://www.criptonoticias.com/informacion/que-es-la-mineria-de-bitcoins-criptomonedas/

[3] ¿Qué es Bitcoin? - https://www.criptonoticias.com/informacion/que-es-bitcoin/

[4] Whitepaper de Bitcoin explicado en español - https://academy.bit2me.com/paper-original-

bitcoin-en-espanol/#Prueba-de-trabajo

[5] Bitcoin Problems & Issues in 2018 - https://www.abitgreedy.com/bitcoin-problems/

[6] The 5 Major Problems with Bitcoin and Blockchain Technology -

https://blockchainreview.io/blockchain-bitcoin-problems-limitations-issues-weaknesses/

[7] Lightning Labs - https://lightning.engineering/

[8] Lightning Network Scalable, Instant Bitcoin/Blockchain Transactions -

https://lightning.network/

[9] Lightning App Directory - https://dev.lightning.community/lapps/

[10] Tutorial Lightning Network LND - https://dev.lightning.community/tutorial/01-

lncli/index.html

[11] LND Overview and Developer Guide - https://dev.lightning.community/overview/

[12] LightningJ - https://www.lightningj.org/

[13] Slack Lightning group - https://lightningcommunity.slack.com/

[14] Quartz Tutorials - http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/

[15] Jersey and Guice: a perfect combination for writing RESTful APIs -

https://sites.google.com/a/athaydes.com/renato-athaydes/posts/jersey_guice_rest_api

[16] How to write a Java gRPC client for the Lightning Network Daemon -

https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/java.md

[17] CronMaker - http://www.cronmaker.com/

[18] Blockchain: Qué es y cuales podrían ser sus usos y ventajas en la Industria 4.0

https://grupogaratu.com/que-es-blockchain-usos-y-ventajas/

[19] Lightning Desktop App por Lightning Labs - https://github.com/lightninglabs/lightning-

app

[20] Yall’s - https://yalls.org/

[21] lnd.fun - http://lnd.fun/

Page 88: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

82

Anexo I: Manual de usuario del cliente Seguidamente se mostrarán cuáles son los diferentes métodos a los que tiene acceso el cliente

para operar con el servicio de loterías.

Cada apartado se compondrá de las siguientes partes:

1. Descripción

2. Imagen generada por SoapUI que muestra la dirección a realizar la petición, Json de la

petición y de la respuesta.

3. Posibles aclaraciones

1. Creación de cartera Creación de la cartera del usuario con la que podrá operar haciendo transferencias con el

protocolo Lightning Network.

Ilustración 37 - Manual - Creación de cartera

Page 89: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

83

2. Restauración de cartera Restauración de la cartera. Es necesario conocer las 24 palabras generadas en la creación de la

cartera para poder restaurarla.

Ilustración 38 - Manual - Restauración de cartera

3. Desbloqueo de cartera Desbloqueo de cartera en situaciones en las que el nodo se haya caído y ya no estemos

autenticados.

Ilustración 39 - Manual - Desbloqueo de cartera

Page 90: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

84

4. Consulta de saldo Consulta de saldo de la cartera.

Ilustración 40 - Manual - Consulta de saldo

5. Compra de boletos Procedimiento para la compra de boletos de un sorteo determinado

Ilustración 41 - Manual - Compra de boletos

6. Consulta de saldo en los canales Se consultan todos los fondos de todos los canales abiertos.

Ilustración 42 - Manual - Consulta de saldo en los canales

Page 91: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

85

7. Extraer fondos de los canales Se extraen todos los fondos de todos los canales abiertos.

Ilustración 43 - Manual - Extraer fondos

8.Movimientos de pago Listado de movimientos de pago relacionados con la cartera

Ilustración 44 - Manual - Movimientos de pago

9. Transferencias a otra cuenta Transferencias efectuadas a otra cuenta. Puede o no existir una ruta válida. En caso de no existir

se creará una directa con el destinatario. El canal al finalizar la transferencia queda abierto, por

lo que el saldo no se verá reflejado en la cartera de destino hasta que el canal se cierre.

Ilustración 45 - Manual - Transferencias a otra cuenta

Page 92: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

86

10. Ver notificaciones Ver las notificaciones de los premios conseguidos.

Ilustración 46 - Manual - Ver notificaciones

11. Marcar notificación como leída.

Ilustración 47 - Marcar notificación como leída

12. Listar todos los sorteos

Ilustración 48 - Manual - Listar todos los sorteos

Page 93: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

87

Explicación de algunos campos de la respuesta:

• award: premio (price).

• price: precio de cada boleto.

• amountTicket: Número de boletos que he comprado para ese sorteo.

• priceTotal: Total de dinero gastado en comprar participaciones para este sorteo.

• totalParticipations: Número total de boletos a la venta.

• currentParticipations: Número total de boletos vendidos.

13. Listar los sorteos pendientes

Ilustración 49 - Manual - Listar los sorteos pendientes

14. Listar los sorteos pendientes en los que participo

Ilustración 50 - Manual - Listar los sorteos pendientes en los que participo

Page 94: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

88

15. Listar todos los sorteos en los que he participado

Ilustración 51 - Manual - Listar todos los sorteos en los que he participado

Anexo II: Manual de usuario del administrador.

1. Configuración de los sorteos Para añadir un nuevo tipo de sorteo, se debe añadir un nuevo registro en la tabla raffleTypes y

crear el sorteo en la tabla raffles, poniendo en el campo tipo, el id del nuevo tipo creado.

A continuación, debemos de especificar una configuración de cron en la clase QuartzListener

para que programe la ejecución de este nuevo tipo de sorteo.

1.1 Base de datos

Ilustración 52 - Manual - Tabla raffleTypes

En la tabla raffleTypes, tenemos los 4 distintos sorteos que están configurados actualmente.

Explicación de la tabla:

• name: nombre del sorteo

• maxTickets: número máximo de boletos que se pueden comprar antes de que el sistema

bloquee el sorteo. Podría suceder que se compraran más boletos de los permitidos porque

dos o más usuarios están comprando a la vez los últimos boletos disponibles y no se están

realizando controles de bloqueo. Pero eso no tiene ninguna importancia ya que el cálculo

del premio se realiza de forma dinámica con respecto al número de boletos comprados. El

máximo se establece, para tener más o menos acotados el importe de los premios.

• price: Precio de un boleto.

• Info: Cadena de texto informativa.

• day: Día de la semana en el que se celebrará el sorteo. Ejemplo: domingo 1 y sábado 7.

Page 95: TRABAJO FINAL DE GRADO · D/Dª Jorge Fernández Molines, autor del Trabajo de Fin de Título Block Lotto, correspondiente a la titulación Grado en Ingeniería Informática, en colaboración

Trabajo de Fin de Grado – Cursos 2018/2019 - ENERO

BLOCKLOTTO

89

• hour: Hora del día en el que se celebrará el sorteo. Hora GMT.

1.2 Quartz

En la clase QuartzListener se programa cuando queremos realizar las comprobaciones para

bloquear y celebrar un sorteo.

Ilustración 53 - Manual - Configuración cron

Existe una herramienta [17] que puede ayudar a la hora de crear nuevas string de cron

compatibles con Quartz.