Curso para desarrolladores de Bitcoin: ¡crea tu propia billetera Bitcoin! | Humberto Cezar | Skillshare

Velocidad de reproducción


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Curso para desarrolladores de Bitcoin: ¡crea tu propia billetera Bitcoin!

teacher avatar Humberto Cezar, Software Developer & Bitcoin Pleb

Ve esta clase y miles más

Obtenga acceso ilimitado a todas las clases
Clases enseñadas por líderes de la industria y profesionales activos
Los temas incluyen ilustración, diseño, fotografía y más

Ve esta clase y miles más

Obtenga acceso ilimitado a todas las clases
Clases enseñadas por líderes de la industria y profesionales activos
Los temas incluyen ilustración, diseño, fotografía y más

Lecciones en esta clase

    • 1.

      Introducción

      7:10

    • 2.

      Descarga, configuración y funcionamiento del nodo Bitcoin Core e IntelliJ IDEA Descarga

      6:33

    • 3.

      ¿Qué es Bitcoin?

      3:03

    • 4.

      Transacciones de Bitcoin y claves privadas

      6:32

    • 5.

      Billeteras Bitcoin, la cadena de bloques y la minería

      3:51

    • 6.

      La red, el ecosistema y los principios de Bitcoin

      5:49

    • 7.

      Comienza el proyecto

      2:59

    • 8.

      Configurar la GUI

      9:55

    • 9.

      Crea nuestra primera prueba

      10:18

    • 10.

      Semillas mnemónicas

      2:11

    • 11.

      Crea una ventana de diálogo de billetera

      11:56

    • 12.

      Crea la semilla mnemónica

      7:33

    • 13.

      Crea buttons y validaciones en la ventana de la billetera

      10:30

    • 14.

      La billetera actual observable

      11:16

    • 15.

      La pestaña de Recibe Bitcoin

      8:29

    • 16.

      Direcciones de Bitcoin y carteras HD

      13:52

    • 17.

      Crea las claves públicas extendidas de nuestra billetera

      16:40

    • 18.

      Genera direcciones en Segwit

      10:19

    • 19.

      Comprende las direcciones de Segwit e introducción a los entornos de red de Bitcoin

      4:34

    • 20.

      Genera direcciones en Segwit – Parte II

      9:10

    • 21.

      Añade soporte para entornos de prueba de red principal, red de prueba y Reg

      7:41

    • 22.

      Prepara nuestro nodo principal de Bitcoin para comunicarte con nuestra billetera

      3:13

    • 23.

      Crea el cliente de Node para crear y listar billeteras

      15:06

    • 24.

      Clientes de Node para cargar una billetera, obtener una nueva dirección, verificar nuestro saldo y minar Bitcoins

      11:21

    • 25.

      Envía bitcoins desde el nodo a la aplicación

      14:25

    • 26.

      La tabla de direcciones

      8:42

    • 27.

      Importa nuestras direcciones de aplicación a nuestro nodo de Bitcoin

      10:18

    • 28.

      Llama de forma asíncrona a nuestro nodo de Bitcoin

      9:50

    • 29.

      Escucha las transacciones desde el nodo con ZeroMQ

      14:09

    • 30.

      Transacciones de Bitcoin: entradas, salidas, scripts y el conjunto de UTXO

      18:31

    • 31.

      Obtén UTXO del nodo y filtralos

      11:46

    • 32.

      Actualiza las direcciones actuales de la billetera

      11:07

    • 33.

      Muestra información de direcciones en la tabla de direcciones

      13:21

    • 34.

      Más escenarios de prueba para recibir bitcoins y evitar la reutilización de direcciones

      14:09

    • 35.

      Mejora las pruebas de recepción de Bitcoin. Recibe más transacciones que direcciones

      10:33

    • 36.

      Genera más direcciones

      15:50

    • 37.

      Confirmaciones de pruebas

      7:33

    • 38.

      La tabla de transacciones

      8:03

    • 39.

      Completa la tabla de transacciones

      14:03

    • 40.

      Mejora las pruebas para la tabla de transacciones y ejecuta nuestra aplicación en la red de pruebas

      17:10

    • 41.

      Escucha los bloques y los saldos de formato

      12:55

    • 42.

      El saldo total de la billetera

      5:50

    • 43.

      Cálculo y muestra el saldo total de la billetera

      8:57

    • 44.

      Añade más pruebas para la función de saldo total

      3:37

    • 45.

      La pestaña de Enviar Bitcoin

      11:11

    • 46.

      Tarifas y tamaños de transacción

      6:48

    • 47.

      Crea la calculadora del tamaño de la transacción y el cliente de tarifa inteligente de estimación de nodos

      13:33

    • 48.

      Selección de monedas y polvo

      6:08

    • 49.

      Implementar la calculadora de polvo y otras utilidades

      9:24

    • 50.

      Implementar el selector de monedas aleatorias

      8:40

    • 51.

      Cómo se construyen y validan las transacciones en Segwit

      7:44

    • 52.

      Implementar el creador de transacciones

      14:03

    • 53.

      La ventana de diálogo Enviar transacciones

      14:21

    • 54.

      Muestra los datos de las transacciones en la ventana de diálogo de Enviar Bitcoin

      15:43

    • 55.

      Cómo funcionan las firmas de transacciones

      5:25

    • 56.

      Cómo manejarán nuestras transacciones enviadas nuestra billetera y nodo

      3:25

    • 57.

      Firma y envía transacciones de Segwit

      16:49

    • 58.

      Tablas y saldos de transacciones y direcciones

      18:13

    • 59.

      Cambia de dirección. Añade una alerta de error por espadas incorrectas

      20:53

    • 60.

      Más mensajes de error y pruebas para la función Send Bitcoin

      14:55

    • 61.

      Un refactor necesario

      17:39

    • 62.

      Un refactor necesario Parte II

      26:45

    • 63.

      Direcciones de Segwit anidadas

      7:50

    • 64.

      Recibe Bitcoin en direcciones de Segwit anidadas

      17:01

    • 65.

      Envía Bitcoin a direcciones de Segwit anidadas y prueba nuestra billetera en la red de pruebas

      9:54

    • 66.

      Envía Bitcoin a direcciones heredadas

      14:23

    • 67.

      Ahorra y cifra nuestra billetera

      16:31

    • 68.

      El menú de Carga billetera

      14:03

    • 69.

      Carga una billetera

      11:47

    • 70.

      Función de negación plausible, refactorización y más pruebas para la cartera de carga

      19:08

    • 71.

      Direcciones, transacciones y saldos correctivos

      12:13

    • 72.

      Actualiza el número de direcciones generadas y optimiza las pruebas

      11:54

    • 73.

      Importa una billetera con la semilla mnemónica

      19:27

    • 74.

      Validación de direcciones

      19:24

    • 75.

      Crea una barra de progreso

      13:27

    • 76.

      Actualización de dependencias

      7:17

    • 77.

      Administra nuestra billetera en el entorno principal de la red

      7:46

    • 78.

      Clase adicional - Bitcoin Core v26

      3:14

  • --
  • Nivel principiante
  • Nivel intermedio
  • Nivel avanzado
  • Todos los niveles

Generado por la comunidad

El nivel se determina según la opinión de la mayoría de los estudiantes que han dejado reseñas en esta clase. La recomendación del profesor o de la profesora se muestra hasta que se recopilen al menos 5 reseñas de estudiantes.

90

Estudiantes

--

Proyecto

Acerca de esta clase

¡Bienvenido al curso de desarrolladores de Bitcoin! Mi nombre es Humberto, y me complace presentarte el primer y único curso en el que aprenderás Bitcoin creando una billetera Bitcoin de escritorio.

En este curso, aprenderás cómo funciona Bitcoin desde un punto de vista técnico. Más específicamente, aprenderás en detalle cómo funciona una billetera Bitcoin. Además, aprenderás cómo funciona un nodo de Bitcoin y cómo administrarlo. Veremos cómo interactúa con nuestra billetera y otros nodos. También aprenderemos cómo funciona la red Bitcoin y cómo logra un consenso.

Los conceptos clave de Bitcoin que aprenderemos incluyen transacciones, direcciones, semillas, llaves, saldos, la cadena de bloques, la minería y la billetera.

Como crearemos una aplicación de escritorio a lo largo del curso, el estudiante tendrá la oportunidad de practicar las siguientes habilidades de ingeniería de software, que tienen una gran demanda en la industria del software:

  • El paradigma de la programación orientada a objetos, en el que se basa nuestra billetera.
  • Desarrollo basado en pruebas (TDD). La mayoría de las funciones que crearemos seguirán la forma de hacer las cosas con TDD. Como sugiere el nombre de este enfoque, para cada función, primero crearemos las pruebas y ellas guiarán el desarrollo posterior de las funciones.
  • Mejores prácticas de seguridad de aplicaciones. Nos preocuparemos mucho por las mejores prácticas de seguridad de las aplicaciones y trataremos la aplicación como un sistema de misión crítica. Personalmente, tengo una gran participación en esta aplicación y me esfuerzo mucho para minimizar la posibilidad de que alguien pierda fondos con esta aplicación.
  • Mejores prácticas de programación. Los principios de SOLID y Clean Code impregnan la cultura de nuestro código. Este curso tiene muchos ejemplos de mejores prácticas de programación.

Aprende haciendo.  Alrededor del 17% de este curso se compone de teoría. El resto se compone de clases prácticas. El curso está muy centrado en los códigos e intercalado con algunas presentaciones cuando es necesario. Debajo de cada video, puedes encontrar enlaces adicionales y material de estudio en la página de Proyectos y Recursos. Construirás una billetera Bitcoin de escritorio y aprenderás los conceptos importantes de Bitcoin mientras lo haces.

Se recomienda que el estudiante tenga un buen conocimiento de Programación orientada a objetos antes de tomar este curso. Se necesitan conocimientos de Java o idiomas similares. Aunque este curso presenta diferentes conceptos de ingeniería de software, nos centramos en comprender Bitcoin. Si el estudiante quiere conocer en detalle algunos de los conceptos de ingeniería de software que se mencionan en este curso, tendrá que usar otras fuentes a lo largo del curso para comprenderlos mejor.

Conoce a tu profesor(a)

Teacher Profile Image

Humberto Cezar

Software Developer & Bitcoin Pleb

Profesor(a)

I have 5+ years of experience as a Professional Software Developer, working especially in the e-commerce industry.

I’ve been a bitcoin enthusiast since 2016. I’ve been heavily studying Bitcoin since then. I’ve developed the open-source bitcoin-java library.

I’ve built the Bitcoin Education initiative to concentrate on providing Bitcoin education for developers worldwide.

Ver perfil completo

Habilidades relacionadas

Desarrollo Desarrollo web
Level: Intermediate

Valoración de la clase

¿Se cumplieron las expectativas?
    ¡Superadas!
  • 0%
  • 0%
  • Un poco
  • 0%
  • No realmente
  • 0%

¿Por qué unirse a Skillshare?

Mira las galardonadas Skillshare Originals

Cada clase tiene lecciones cortas y proyectos prácticos

Tu membresía apoya a los profesores de Skillshare

Aprende desde cualquier lugar

Ve clases sobre la marcha con la aplicación de Skillshare. Progresa en línea o descarga las clases para verlas en el avión, el metro o donde sea que aprendas mejor.

Transcripciones

1. Introducción: Hola, Bienvenido al curso para desarrolladores de Bitcoin. Mi nombre es Alberto, y me complace presentarte el primer y único curso en el que aprenderás Bitcoin construyendo una billetera Bitcoin de escritorio. Entonces comencemos explicando lo que aprenderás en este curso. En definitiva, aprenderás cómo funciona Bitcoin desde un punto de vista técnico. Más específicamente, aprenderás cómo funciona una billetera Bitcoin en detalle. Además, aprenderás cómo funciona un nodo Bitcoin y cómo ejecutarlo. Veremos cómo interactúa con nuestra cartera y otros nodos. También aprenderá cómo funciona la red Bitcoin y cómo logra el consenso. conceptos que aprenderemos incluyen transacciones, direcciones , semillas, claves, saldos , blockchain, minería y billetera. Dado que construiremos una aplicación de escritorio a lo largo del curso, el estudiante tendrá la oportunidad de practicar las siguientes habilidades de ingeniería de software que tienen una gran demanda en la industria del software. El paradigma de programación orientada a objetos en el que se basa nuestra billetera. La mayoría de las características se construirán, seguirán la forma de desarrollo impulsada por pruebas de hacer las cosas. Como sugiere el nombre de este enfoque, para cada característica se construirán sus pruebas primero y las pruebas guiarán a la característica un mayor desarrollo también se preocuparán mucho por la aplicación mejores prácticas de seguridad, y tratar la aplicación como un sistema de misión crítica. Yo personalmente tengo piel en el juego en esta aplicación, y pongo mucho esfuerzo en minimizar la posibilidad de que alguien pierda fondos con ella. Además, este curso tiene muchas mejores prácticas de programación, ejemplos, principios sólidos y código limpio que impregnan la cultura de nuestro código. Ahora, veamos cómo aprenderás en este curso. Seguiremos la metodología de aprender haciendo. Alrededor del 17% de este curso está compuesto por teoría, el resto está compuesto por clases prácticas. lo que el curso tiene muy centrado en el código, intercalado con algunas presentaciones cuando es necesario. Debajo de cada video, puedes encontrar enlaces adicionales y material de estudio en la página Proyectos y Recursos. Construirás una billetera Bitcoin de escritorio, aprendiendo conceptos importantes de Bitcoin mientras lo haces. Ahora, enumeremos los requisitos recomendados para tomar este curso. Se recomienda que el alumno tenga un buen conocimiento de la programación orientada a objetos. El alumno debe conocer Java o idiomas similares antes de tomar este curso. Aunque este curso presenta diferentes conceptos de ingeniería de software, nuestro enfoque es entender Bitcoin. Si el alumno quiere conocer a detalle algunos de los conceptos de ingeniería de software se tocaron en este curso. Tendrá que utilizar otras fuentes a lo largo del curso para entenderlas mejor. Necesitarás una computadora con Windows, macOS o Linux con conexión a Internet. Presentaremos este curso usando Windows. Pero como Java es compatible multiplataforma, cada código de este curso funcionará de la misma manera en estos tres sistemas operativos. La única diferencia será instalar el software necesario en cada plataforma, pero puedes encontrar fácilmente guías para instalarlos en estos sistemas operativos. Necesitarás al menos 30 gb de espacio libre para ejecutar el nodo Bitcoin en el entorno de red de prueba. Opcionalmente, si pretendes ejecutar la aplicación en el entorno de red principal, necesitarás al menos 430 gb de espacio en disco para descargar la red blockchain principal. Pero no te preocupes, usaremos el entorno de red principal solo en el último video del curso. Así que tendrás tiempo de sobra para descargarlo antes de necesitarlo. Ahora, hablemos un poco más sobre la billetera que construirás a lo largo del curso. Me referiré a esta cartera como BYOD W, acrónimo para construir tu propia billetera, empezará a desarrollar esta aplicación con Java 16, pero la actualizaremos más adelante en el curso. Diversion 19 utilizará el marco Spring Boot versión 2.5, 0.4, que proporcionará un contenedor de inyección de dependencia y muchas facilidades para ayudarnos a construir nuestra aplicación. Posteriormente en el curso, lo actualizaremos a la versión 2.7, 0.5. Usaremos Java FX versión 16 en el proyecto. actualizaremos más tarde a la versión 19. Esta biblioteca brindará clases que nos ayudarán a construir la interfaz gráfica de usuario de las aplicaciones, también conocida como gooey. Para las pruebas, usaremos Groovy, el marco Spark y la ética de prueba para crear billeteras, direcciones de semillas, transacciones y otras operaciones de Bitcoin usarán la biblioteca Java de Bitcoin de código abierto, que construí especialmente para este curso. Usaremos el Bitcoin Core Node versión 22 para la comunicación con la cadena de bloques. Posteriormente en el curso, lo actualizaremos a la versión 23. Aunque el nodo Bitcoin Core puede generar billeteras y direcciones, lo utilizará únicamente para recuperar datos y enviar datos a la cadena de bloques. Operaciones como generar semillas, direcciones, construcción y firma de transacciones serán realizadas por nuestra aplicación. La excepción será para las pruebas. En estos casos, utilizaremos la API Bitcoin Core Node RPC para generar direcciones, enviar transacciones y minar bloques en los entornos de prueba, por lo tanto, nos familiarizaremos con los más importantes Bitcoin Core Note RPC API métodos y construir un cliente para comunicarse con él desde nuestra aplicación. Como la base de datos utilizará la implementación SQL Java H SQL DB utilizará una integración fluida con la biblioteca Spring Boot Data JPA para comunicarse con la base de datos. Finalmente, usaremos la idea IntelliJ como IDE para construir este proyecto. Todo el código presentado en este curso es código abierto y está disponible en nuestra página de GitHub. Para cada clase práctica, la página Proyectos y Recursos contendrá un enlace con la diferencia de código entre las dos últimas clases prácticas para conveniencia de los estudiantes. Ahora, vamos a presentar quien soy. Mi nombre es Alberto Salazar, y seré tu instructor en este curso. Tengo más de cinco años de experiencia como desarrollador de software profesional, trabajando especialmente en la industria del comercio electrónico. He sido un entusiasta de Bitcoin desde 2016. Había estado estudiando mucho Bitcoins desde entonces. Desarrollo la biblioteca Java Bitcoin de código abierto, que usaremos en este curso. He construido la iniciativa de educación de Bitcoin para concentrar mis esfuerzos en brindar educación sobre Bitcoin a desarrolladores de todo el mundo. Síguenos en Twitter para recibir nuestras últimas actualizaciones. Concentré todo el código para este curso, incluyendo la biblioteca Bitcoin Java en nuestra página de GitHub. También tenemos un sitio web cuya dirección es www punto bitcoin educación punto sitio. Allí tenemos algunos artículos técnicos que pueden servir como material de estudio adicional. Compruébalo como última palabra. Quiero decir que se puso mucho trabajo en hacer este curso. Tomó más de dos años en la elaboración y casi todo mi tiempo libre durante este periodo. Así que por favor, si tienes alguna dificultad o encuentras algún problema con este curso, contáctame antes de darle una calificación baja para que podamos ayudarte con tu problema. Con mucho gusto haré todo lo posible para que tengas una gran experiencia de aprendizaje. Muchas gracias por su atención y nos vemos en el siguiente video. 2. 0 Requisitos de instalación Skillshare 2: En este video, te presentaremos el software necesario que tendrás que descargar e instalar antes de pasar a los siguientes videos del curso. Entonces comencemos con el Bitcoin Core Node. El Bitcoin Core Node es la implementación original de Bitcoin. Es responsable de comunicarse con la cadena de bloques, crear, recibir, enviar y validar transacciones de Bitcoin, recibir bloques y más. Como hemos dicho en el video anterior, las funciones principales que dependerán del nodo Bitcoin Core son las relacionadas con la comunicación con la cadena de bloques. Entonces vayamos al sitio web de Bitcoin core.org. Instalará Bitcoin Core versión 22. Te preguntarás ¿por qué no instalar la versión 23? Cuando empecé a hacer este curso, la última versión disponible era 22. Hay una pequeña diferencia en la API de gRPC en la versión 23 que hará que un método de nuestra aplicación no funcione correctamente. En uno de los últimos videos del curso, actualizaremos el nodo Bitcoin dos versión 23 y haremos que nuestra aplicación sea compatible con él. Pero por ahora, instalemos la versión 22. Para hacerlo, haga clic en el botón de liberación en la parte superior de la pantalla, luego haga clic en el enlace Bitcoin Core 22. A continuación, haga clic en este enlace en la página. Esta página contiene archivos de instalación para cada sistema operativo. Ya que estoy usando Windows, descargaré el que termina con punto EXE. Si estás usando macOS, descargarás el que termina con dot DNG. Para distribuciones Linux, elija el archivo punto GZ adecuado de acuerdo con la distribución que utilizará en la página Proyectos y Recursos, hay enlaces con instrucciones de instalación para cada sistema operativo. Para Windows, después de descargar el archivo, ábralo y sigue las instrucciones de instalación en pantalla. No voy a hacer eso porque ya lo he instalado en mi máquina. Pero es un proceso sencillo. En la última fase de la instalación , te preguntará si quieres abrir el software. No lo abras todavía. Interactuará con el nodo Bitcoin a través de la interfaz de línea de comandos. Si abres el nodo haciendo clic en su icono, éste abrirá una interfaz gráfica de usuario y empezará a descargar la cadena de bloques en el entorno de la red principal, que aún no queremos hacer. Ahora, vamos a configurar nuestro nodo Bitcoin. Para ello, tendremos que crear un archivo llamado bitcoin.com y la carpeta apropiada de la aplicación Bitcoin. La ubicación de esta carpeta depende del sistema operativo que estés usando. Este sitio web en la pantalla muestra la ubicación predeterminada donde se tiene que crear este archivo para cada sistema operativo. Para crearlo, abre un archivo de texto y guárdalo con el nombre bitcoin.com de la carpeta apropiada para tu sistema operativo. Ahora, escribe la misma configuración que ves en la pantalla en tu archivo, o copia y pega el contenido de la página Proyectos y Recursos en él. No te preocupes, te explicaremos lo que significa cada línea de este archivo en un video posterior. Por ahora, tendrás que decidir dónde quieres almacenar los datos de blockchain en tu computadora, tendrás que elegir una ruta con acceso a al menos 30 gb para la red de prueba blockchain, o una 430 adicional gb para la cadena de bloques de red principal. Opcionalmente, establezca la configuración DIR de datos a la ruta elegida en este archivo. En mi caso, decidí almacenar los archivos blockchain en la unidad E en la carpeta de datos de Bitcoin, como se ve en la pantalla. Ahora, si ejecutamos el nodo Bitcoin con esta configuración, se ejecutará en la red principal y comenzará a descargar la red principal blockchain. Como su nombre indica, el entorno de red principal es el principal entorno bitcoin donde la blockchain es grande y los bitcoins tienen valor, solo ejecutará el entorno neto principal en el último video del curso. Antes de eso se ejecutará en el entorno de red de prueba, que se utiliza para las pruebas. Para ejecutar nuestra nota en el entorno de red de prueba, agreguemos una línea escrita de prueba neta igual a una en el archivo bitcoin.com. Ahora usando el terminal, vayamos a la carpeta donde instalaste el Bitcoin Core Node. Dentro de la carpeta demonio, ejecuta la aplicación Bitcoin D así. En los registros de la consola. Observe que estamos funcionando efectivamente en el entorno de red de prueba y todos sus datos se almacenarán en la carpeta indicada. Bien, eso significa que nuestro nodo está trabajando con la configuración que hemos establecido en el archivo bitcoin.com. Ahora, esperemos a que nuestro nodo se conecte a otros nodos y comencemos a descargar y validar la cadena de bloques. Bien, las líneas que comienzan con el tip de actualización de texto indica que comenzó a descargar la cadena de bloques. Cada una de estas líneas indica un bloque de transacciones de Bitcoin descargadas. El avance en cada línea indica cuánto se hunde la cadena de bloques. En mi caso, indica que se descargó cerca del 98% de la cadena de bloques neta de prueba. Cuando este valor es igual a uno, indica que nuestra copia de la cadena de bloques está completamente sincronizada con las de otros nodos. Para el entorno de red de prueba, puede tomar algunas horas para que suceda. Puedes dejarlo hundido mientras procedes a ver el resto del curso, ya que lo usaremos solo después de algunos videos. Para salir de la aplicación, puedes presionar Control más C o Comando más C si estás usando Mac OS, si vuelves a iniciar la nota, comenzará a descargar la cadena de bloques donde se detuvo. Después de terminar de descargar el entorno de red de prueba, opcionalmente puede cambiar el archivo bitcoin dot conf y comenzar a descargar la cadena de bloques de red principal ejecutando la nota en el entorno de red principal, solo usará el entorno de red principal en el último video del curso, por lo que tendrás mucho tiempo para descargarlo. El otro requisito inicial de este curso es la idea IntelliJ Java IDE. Es el software que usaremos para escribir el código y ejecutar nuestra aplicación. Si no lo tienes, ve a la página web en la pantalla para descargarla. Descargue e instale la edición comunitaria para su sistema operativo siguiendo las instrucciones del sitio web. 3. ¿Qué es Bitcoin?: Hola, bienvenidos de nuevo al curso de desarrolladores de Bitcoin. En esta sección del curso te dará una visión general de Bitcoin. Los conceptos presentados en esta sección, aportaremos los conocimientos básicos necesarios para entender lo que viene en el resto del curso. Entonces comenzaré con la pregunta, ¿qué es Bitcoin? Bitcoin con una B mayúscula es un protocolo de comunicación. Este protocolo es un conjunto de reglas que permite el intercambio de mensajes entre las entidades participan en la red Bitcoin. Bitcoin con b minúscula es una criptomoneda. Una criptomoneda es una forma de moneda digital que podemos cambiar por bienes u otros activos. La parte criptográfica del nombre proviene de la criptografía, que protege las transacciones y otras operaciones de Bitcoin. Bitcoin también es un sistema de pago. Podemos enviar y recibir pagos de Bitcoin hacia y desde otros participantes de la red Bitcoin. Hablando de redes, Bitcoin también es una red peer to peer, lo que significa que está compuesta por entidades o nodos que se comunican directamente entre ellos sin la participación de servidores centralizados. La siguiente pregunta es, cuándo se inventó el bitcoin? Bitcoin fue inventado en 2008 por Satoshi Nakamoto con la publicación del libro blanco, Bitcoin, uh, sistema de efectivo electrónico peer-to-peer. En este trabajo, que recomiendo encarecidamente leer, Satoshi describe las partes básicas de Bitcoin. Nadie sabe quién es realmente Hitoshi Nakamoto, o si es incluso un nombre real o varias personas. Quienquiera que sea Satoshi, en 2009, publicó el primer bloque de Bitcoin llamado bloque génesis y puso a trabajar la red Bitcoin. Si no sabes lo que es un bloque de Bitcoin, no te preocupes. Voy a explicar en breve. Entonces, ¿qué tiene de genial Bitcoin? ¿Cuál es la innovación de Bitcoin? Bitcoin fue la primera moneda digital, bien lograda. Antes de Bitcoin, hubo algunos intentos de crear monedas digitales, pero todas fallaron debido a problemas que Bitcoin resolvió más tarde. Uno de estos problemas es el problema del doble gasto, que bitcoin fue el primero en resolver de manera descentralizada. Ocurre cuando una persona gasta dos veces una unidad monetaria. Por lo que una de las transacciones se invalida posteriormente, haciendo que el destinatario de la transacción invalidada pierda dinero. Bitcoin también se encargó de inventar la cadena de bloques, que se utilizó para resolver el problema del doble gasto. La cadena de bloques es una estructura de datos responsable de almacenar todas las transacciones de Bitcoin. Permite la validación de todas sus transacciones a cualquiera que tenga acceso a ella, pero más sobre eso más adelante. Bitcoin también introdujo el concepto de escasez digital. Significa que a diferencia de los archivos en tu computadora que se pueden copiar y distribuir indefinidamente, Bitcoin solo puede ser transferido por su propietario y no puede ser copiado y distribuido libremente. 4. Transacciones de Bitcoin y llaves privadas: Ahora profundizaremos un poco más en los detalles internos de Bitcoin. Voy a explicar Bitcoin de micro a macro. Es decir, voy a hablar transacciones de Bitcoin y claves privadas, luego un poco sobre blockchain y minería. Después terminaré el resumen explicando el ecosistema Bitcoin. Entonces comencemos con la pregunta, ¿dónde está la criptomoneda y el sistema? O en otras palabras, ¿dónde está el Bitcoin con una b minúscula en el sistema? La respuesta es, está en una transacción. Esta figura muestra una transacción común de Bitcoin con una entrada y dos salidas. Una transacción de Bitcoin puede tener muchas entradas y salidas, pero en muchos casos, solo tienen una entrada y dos salidas. En una transacción de Bitcoin, tenemos la información de dónde vino el Bitcoin en la entrada y hacia dónde va el Bitcoin en la salida. En este ejemplo, la entrada cero contiene una instrucción que dice que esta entrada vino de John, fue firmada por John y contenía un Bitcoin. La primera salida llamada la salida cero, dice a María contener 0.9 Bitcoin. En la salida uno, le dice a John contiene 0.099 Bitcoin. Esta salida es el cambio de la transacción. En la mayoría de los casos, necesitamos incluir un cambio porque cuando gastas Bitcoin de una transacción, tienes que gastar todas las unidades de la entrada. Entonces esto genera la necesidad crear una salida adicional, que es el cambio. Entonces, si tu entrada contiene más bitcoins, entonces quieres enviar a otra persona, entonces debes crear una salida adicional, el cambio a ti mismo. Tenemos el concepto de UTXO, lo que significa salida de transacción no gastada. Un bitcoin está más específicamente dentro de un UTXO. Una entrada de transacción debe referirse a un UTXO de una transacción anterior para poder gastar ese Bitcoin en esta transacción. Si nota la suma de cantidades de salidas es menor que la cantidad en la entrada. ¿Por qué es eso? La diferencia se debe a la cuota menor. Cada transacción de bitcoin debe separar un monto por la tarifa menor para que su transacción pueda ser incluida en la cadena de bloques por un menor. Por lo que el monto de la tarifa de transacción es la diferencia entre la suma de Bitcoins presentes en las salidas y la suma de Bitcoins presentes en las entradas. Otra pieza importante de información es que Bitcoin se puede dividir en 100 millones de Satoshi. Por lo tanto, en esta transacción de ejemplo, podríamos haber dicho que los insumos que contenían 100 millones de Satoshi en el cero de salida contienen 90 millones de Satoshi y el de salida uno contiene 9,900,000 De Satoshi. La cuota menor era de 100 mil Satoshi. Estos son otros ejemplos de transacciones de Bitcoin. Los pongo aquí solo para demostrar que se pueden tener transacciones con más de una entrada y una salida. Por ejemplo, puede tener una transacción con dos entradas y una salida. Esta transacción no tiene cambio. Se puede tener una transacción con dos entradas y dos salidas. En este caso, la transacción tiene entradas de dos personas diferentes y salidas para dos personas diferentes. Este tipo específico de transacción se llama transacción Coinjoin, que es un tipo de transacción que aumenta la privacidad porque no se pueden vincular entradas específicas a salidas específicas. Se puede tener una transacción con tres entradas y dos salidas. Hay otros tipos de transacciones, como las transacciones multifirma de las que no hablaremos ahora, pero podemos incluirlas más adelante en una sección de curso extra si hay suficiente demanda. Veamos un poco más sobre los detalles de una transacción. En esta imagen, hay dos transacciones, transacción uno y transacción dos. Ambas transacciones tienen entrada y salida. La entrada tiene tres campos, el ID de transacción anterior y el número de salida de una transacción anterior y una firma válida. La salida tiene dos campos, destino, dirección y cantidad, que hace referencia a la cantidad de Bitcoin dentro de la salida. En este caso, la entrada de Transacción dos es el gasto de salida cero de la transacción uno. Para ello, ingrese uno de la transacción a debe referirse al ID de transacción de la transacción uno. También debe referirse al número de salida de la transacción uno, que en este caso es cero. Finalmente, debe contener una firma válida producida con la clave privada utilizada para derivar la dirección de destino a partir de la salida cero. Veremos más detalles sobre esta operación en la siguiente diapositiva. Como puede notar, las claves privadas son una parte fundamental de Bitcoin. Las claves privadas se utilizan para recibir y enviar bitcoins para recibir. Las claves privadas se transforman en claves públicas a través de la multiplicación de curvas elípticas. Entonces, después de una función hash, las claves públicas se transforman en direcciones Bitcoin. Estas son las direcciones de Bitcoin que puedes mostrar a otras personas para recibir Bitcoins. Las claves privadas también se utilizan para asignar transacciones de Bitcoin. Las firmas son necesarias para transferir Bitcoins de una dirección a otra. En esta imagen, tenemos una transacción sin firmar. Cuando combinamos la clave privada con una transacción privilegiada usando el algoritmo de firma digital de curva elíptica, ECDSA, producimos una firma que incluimos en esa transacción. De esta manera, se convierte en una transacción firmada. La misma clave privada que produjo la dirección referida a una entrada cero también se utiliza para desbloquear estos fondos y la transacción actual produciendo la firma. Así, una clave privada se utiliza indirectamente para bloquear fondos en una dirección y para desbloquear fondos de la misma dirección produciendo una firma. Lo importante de las claves privadas y sus transformaciones es que no se puede producir una clave privada a partir de una clave pública, y no se puede producir una clave pública a partir de una dirección de Bitcoin. Tampoco se puede producir una clave privada a partir de una firma. Estas operaciones son sólo en una dirección, tal como muestran estas flechas. Otra característica importante de las transacciones de Bitcoin es que cualquier persona con acceso a una transacción puede validar firmas. Esto es posible porque si se tiene una clave pública, la firma y el mensaje, que en este caso es la transacción. Puedes verificar si una firma es válida para esa clave pública. Y una firma es válida para una clave pública sólo si se produjo con una clave privada que produjo la misma clave pública. 5. Billetes de Bitcoin, la cadena de bloques y la minería: Ahora que tienes un conocimiento básico sobre claves privadas, podemos empezar a hablar de billeteras. Una billetera Bitcoin es, en definitiva, una colección de claves privadas. Hay muchos tipos y estándares de billeteras. Las billeteras tienen un desarrollo independiente con respecto a otros programas de Bitcoin como los nodos. Una regla básica para poseer Bitcoin no es el mantra. Tus llaves, tus bitcoins, no tus llaves, no tus Bitcoins. Esto se debe a que el propietario de una clave privada puede transferir Bitcoins bloqueados por su clave privada y otras transacciones. ¿Qué cosas tienen en común las billeteras Bitcoin? Cuentan con una forma segura de generar y almacenar claves privadas. Pueden comunicarse con los nodos de Bitcoin. Pueden crear, firmar y enviar transacciones de Bitcoin. Pueden generar direcciones de Bitcoin. Observe que la mayoría de estas habilidades son posibles gracias a las transformaciones de claves privadas. Cada operación que utilice claves privadas se puede realizar sin conexión. Solo necesita estar en línea cuando comunica con los nodos de Bitcoin para obtener información de la cadena de bloques y enviar información a la cadena de bloques. Hablando de blockchain, veamos finalmente qué significa esta palabra de moda. El blockchain se utilizó para resolver el problema del doble gasto de manera descentralizada. Lo hace organizando las transacciones en una cadena de bloques para que los bloques válidos no puedan contener transacciones con un UTXO que apareciera en el mismo bloque o en bloques anteriores. Para entender qué es la cadena de bloques, veamos esta cifra. Estos bloques representan bloques de la cadena de bloques. Algunos de sus datos están representados en estos rectángulos más pequeños. Dentro de cada bloque. Un bloque está compuesto por muchas transacciones, un campo llamado hash anterior, que como su nombre indica, es el hash del bloque anterior. Un campo llamado timestamp, que almacena la fecha donde se creó el bloque, y un campo llamado nonce, del que hablaremos en la siguiente diapositiva. Cada bloque produce un hash que se inserta en el siguiente bloque. Los bloques son creados y añadidos a la cadena de bloques en un proceso llamado minería. minería es el proceso donde los bloques se incluyen en la cadena de bloques. los nodos que hacen este proceso se les llama mineros. Para incluir bloques en la cadena de bloques, los mineros deben recolectar transacciones y organizarlas en un bloque. Entonces los menores deben resolver la Prueba de Trabajo, que es un algoritmo necesario para producir bloques válidos. comprobante de trabajo se compone de los siguientes pasos. Primero, un bloque es hash, luego se verifica el número de ceros iniciales del hash resultante. Si este número es mayor o igual al número necesario de ceros para incluir el bloque en la cadena de bloques. El bloque está incluido en la cadena de bloques. Si no, entonces el menor modifica el nonce y repite el proceso. Entonces esta es la función del nonce. Su único propósito es proporcionar variabilidad para que un bloque produzca diferentes hashes. La prueba de trabajo tiene una característica interesante. Cuantos más ceros se requieran para una prueba válida de trabajo, más difícil es encontrarla. Esto hace que la dificultad minera sea fácilmente ajustable. En Bitcoin, la dificultad de minería se ajusta automáticamente, por lo que el tiempo promedio para extraer un bloque es de 10 min. Cuando un menor le importa un bloque, gana una recompensa de bloque y todas las tarifas de transacción de bloque. La recompensa de bloque es la única forma en que se crean nuevos bitcoins. Disminuye a la mitad cada cuatro años en un evento llamado tener. Por lo que cada cuatro años el suministro de nuevos Bitcoins emitidos se hace más escaso. Y se calcula que el último bitcoin será minado en alrededor las 21:40 cuando la oferta total de Bitcoin será igual a 21 millones. 6. La red, los ecosistemas y los principios de Bitcoin: Ahora hablemos de la red Bitcoin. Veamos los pasos básicos de cómo funciona la red Bitcoin. Primero, se envían nuevas transacciones a los nodos. Cada minero reúne las transacciones en un bloque. Cada minero intenta encontrar un bloque de prueba de trabajo lo más rápido posible. Cuando un minero encuentra prueba de trabajo, el menor transmite su bloqueo mental a la red. Otros nodos verifican si el bloque es válido. Para que un bloque sea válido, debe seguir todas las reglas de consenso, como todas las transacciones y debe ser válido y el hash de bloque anterior debe ser igual a la caché de bloques del último bloque válido. Si el bloque es válido, los nodos lo agregan a su Blockchain. Copia. Comienzo menor a trabajar en nuevos bloques usando el campo hash del bloque mental recientemente como hash anterior. Quizás te estés preguntando qué pasa si dos mineros extraen un bloque válido al mismo tiempo. Bueno, cuando esto sucede, provoca una división en la red. Parte de los nodos contendrá una versión de la cadena de bloques con un bloque de un menor y la otra parte de la red contendrá un bloque del otro menor. Pero esta división sólo es temporal. Cuando se mina el siguiente bloque, los dos grupos de nodos considerarán solo la blockchain con más bloques ya que se descarta la blockchain real y la otra blockchain, la probabilidad de que la división de la red persiste disminuye con el tiempo. Por lo que es seguro asumir que después de seis bloques una transacción se liquida para siempre en la cadena de bloques. La inmutabilidad y seguridad de las transacciones de Bitcoin descansa en el hecho de que es casi imposible producir una cadena de bloques válida con más bloques que la original. Tal hazaña requeriría una inmensa cantidad de potencia computacional necesaria para superar la velocidad de generación de bloques de la red original por un tiempo suficiente. Ahora que aprendimos sobre varias partes de Bitcoin, veamos cómo interactúan dentro del ecosistema Bitcoin. Los usuarios de Bitcoin controlan las billeteras. Las billeteras, como aprendiste, son colecciones de claves privadas. Y estas claves privadas pueden ser utilizadas para firmar transacciones y para producir direcciones para recibir transacciones. Los exchanges pueden intercambiar bitcoins por otras criptomonedas y monedas fiduciarias, como el dólar. También puedes intercambiar bitcoins por bienes de comerciantes. Con quien realice transacciones, todas sus transacciones se envían a los nodos de Bitcoin. Cuando un menor ve tu transacción, puede incluirla en un bloque. El minero crea un bloque con muchas transacciones y procede a minar el bloque. Es decir, comienza a calcular la prueba de trabajo de bloque utilizando su hardware. Cuando un menor finalmente encuentra la prueba de trabajo del bloque, transmite el bloque a otros nodos de Bitcoin. Los otros nodos reciben el bloqueo mental recientemente y validado. Si el bloque es válido, los nodos lo agregan a su copia de la cadena de bloques. De esta manera, la red logra consensos sobre el estado actual de la cadena de bloques. Hablemos de los principios de Bitcoin. Los principios de Bitcoin son importantes para entender las decisiones técnicas que se tomaron durante el desarrollo de Bitcoin. Uno de estos principios es el suministro máximo de Bitcoin de 21 millones de Bitcoins. Este límite se fijó al inicio del proyecto. Cambiarlo provocaría que estos arreglos en la economía de Bitcoin. Por lo que es importante mantenerlo así. resistencia a la censura es otro principio importante de Bitcoin. El hecho de que mucha gente pueda ejecutar nodos de Bitcoin hace que sea casi imposible que una autoridad cierre la red. Los desarrolladores de Bitcoin valoran una alta resistencia a la censura. Ser de código abierto es otro principio de Bitcoin. Puede encontrar el software Bitcoin Core forma gratuita en el sitio web de GitHub. Al igual que muchos otros desarrolladores, puedes verificar el código y verificarlo en busca de errores. También puedes participar en su desarrollo. Bitcoin tiene una fuerte comunidad de desarrolladores responsables de su seguridad y nuevas características. Y ser de código abierto es lo que lo permite. Bitcoin no tiene permiso, lo que significa que a cualquiera se le permite ejecutar un nodo Bitcoin, minar y realizar transacciones con Bitcoins. Esa es una de las mayores fortalezas de Bitcoin y lo que lo hace tan popular hoy en día en todo el mundo. Las transacciones de Bitcoin son seudónimas. Eso significa que ninguna información presente en una transacción de Bitcoin puede conectarse sola con las personas. A diferencia del ejemplo desde el principio de la visión general, podría haber sugerido que las transacciones de Bitcoin no contienen los nombres y los ID de los destinatarios y remitentes. Una transacción de Bitcoin muestra solo transferencias entre direcciones bitcoin, que parecían colecciones aleatorias de caracteres. Si alguien descubre que una dirección pertenece a una persona específica, puede rastrear la cantidad de Bitcoin y otras transacciones de esa persona. Pero esa es otra historia. Bitcoin apunta a una alta fungibilidad. fungibilidad es una característica que hace que una unidad de una moneda se valore por igual que cualquier otra unidad de la misma moneda. Eso significa que idealmente cada Bitcoin es valorado y tratado por igual. A menudo se argumenta que Bitcoin no es fungible porque Bitcoins de diferentes transacciones pueden rastrearse y tratarse de manera diferente. Yo diría que aunque es cierto en la práctica, la mayoría de los bitcoins son tratados por igual y se tienen formas de hacer las transacciones más privadas y fungibles. irreversibilidad de las transacciones es otro principio de Bitcoin. Una vez que una transacción se liquida en la cadena de bloques, no se puede revertir. Esta es una característica de seguridad importante porque hace que Bitcoin sea difícil de confiscar. Pero también traslada la responsabilidad de una transacción al centro de Bitcoin. De ahí la necesidad de mantener seguras tus claves privadas. 7. 5 Comienzo de la skillshare del proyecto: En este video, configuraremos un nuevo proyecto Spring Boot que será nuestra billetera Bitcoin. Para ello, usaremos la herramienta de inicializador Spring del sitio web start dot spring dot io. Así que entra al sitio web. Elige el proyecto Maven. El lenguaje es Java, usará esta versión de Spring Boot, pero si no está disponible para ti, puedes elegir la predeterminada como nombre del grupo. Puedes establecer el nombre que quieras. En mi caso, lo configuraré como BYOD w dot wallet. Voy a usar BYOD W como nombre del artefacto, como descripción. Voy a usar billetera Bitcoin. Usaremos la última versión de Java. Si solo conoces versiones anteriores de Java, no te preocupes, características anteriores de Java aún funcionan en la última versión ya que Java es compatible con versiones anteriores. Por último, da clic en Generar para descargar el proyecto, abrirlo y extraer su contenido a la carpeta que desee. Ahora, abriremos el proyecto usando idea inteligente. Después de iniciar el programa, haz clic en Abrir, luego elige la carpeta que acabas de extraer. Haga clic en Trust Project. Espere hasta que IntelliJ idea indexa todos los archivos del proyecto. Después de eso, puede explorar los archivos que inicializador de resorte creó automáticamente. Para verificar si el proyecto se configuró correctamente. Da click en Maven en el lado derecho de la pantalla. Después dentro de la carpeta de ciclo de vida, haga doble clic en Prueba. Uy, tenemos un error de maven. Para resolver ese error, hagamos clic en el cuadro de diálogo de configuración. Cambiemos el camino de casa de Maven para agrupar a Maven tres. Haga clic en Aplicar entonces. Bien. Antes de volver a hacer clic en la prueba, verificaré si la estructura de mi proyecto se configuró correctamente. Entonces voy a hacer clic en Archivo. Entonces la estructura del proyecto se asegura de que el SDK del proyecto tenga la versión Java que eligió el inicializador de primavera. Si no es el caso, haga clic en Agregar SDK y descargue SDK, elija la versión correcta de Java y una de sus implementaciones haga clic en descargar. En mi caso, no voy a hacer eso porque ya tengo la versión correcta. Entonces voy a hacer clic en Cancelar. Asegúrese de que el nivel de lenguaje del proyecto también esté configurado en la versión correcta de Java. Ahora, volvamos a hacer la prueba. Espere hasta que pase la prueba. Genial. La consola indica que la prueba ha pasado. Estamos listos para comenzar a trabajar en nuestra billetera. 8. 6 Configuración de la repetición de habilidades de la GUI: En este video, comenzaremos a construir la primera ventana de nuestra billetera. Para ello, primero agregaremos algunas dependencias a nuestro proyecto. Abra el archivo xml palm dot en la raíz del proyecto. El archivo xml palm dot contiene todas las dependencias externas del proyecto. Vamos a añadir algunas dependencias de Java FX. Java FX es un framework responsable de las características de la interfaz gráfica de usuario. Es muy conocido en la comunidad Java. La versión es 16. La siguiente dependencia es JavaFX, FXML. La versión también es 16. También añadiremos un plugin. Se llama Java FX Maven plugin. Su versión es 0.0, 0.6. Para cargar estas dependencias en su proyecto, haga clic en este icono. Project ha cargado todas las dependencias. Ahora hagamos el código necesario para arrancar nuestra aplicación. Este proceso requiere cierta coordinación entre las formas en que arrancan los efectos Spring Boot y Java. Para ello, primero haremos una nueva clase Java llamada aplicación GUI. Esta clase debe extender la clase de aplicación desde los efectos Java. Y debemos implementar el método start desde la misma clase. Añadiremos una propiedad privada con el contexto de aplicación configurable de tipo. Usaremos a continuación. Aquí agregaremos el método init, que se ejecuta antes del método start, durante la inicialización de la aplicación. El código que acabo de escribir es responsable inicializar nuestras dependencias inyectadas en la aplicación Spring Boot . Ahora pasemos a la clase de aplicación BYOD W. Modifiquemos el método principal. El método principal de esta clase es el primer método llamado cuando ejecutamos nuestra aplicación. Cuando se ejecuta el código que acabo de escribir, primero llamará al método init de la clase de aplicación GUI que al método start de la misma clase. Volvamos a la clase de aplicación GUI. Sigamos implementando el método start. Ahora, llamaremos al método publish event en la propiedad context, pasando un nuevo objeto de evento iniciado GUI, que creará next como argumento. Vamos a crear la clase de evento comenzada pegajosa. Lo crearemos en una nueva carpeta de eventos. Debido a cómo creamos esta clase, el ID ya sabía qué clase teníamos que extender y automáticamente creó el código boilerplate va necesitar muy útil, ¿no es así? Ahora seguiremos implementando nuestro constructor. Llamaremos al súper constructor pasando un objeto de aplicación GUI como argumento. Y asignaremos el argumento etapa primaria a la etapa. La propiedad privada también hará un oyente para esta clase de evento dentro de un paquete llamado oyentes. Añadiremos la anotación de componentes a esta clase. Verás mucho esta anotación a lo largo del curso. Es de Spring Boot y su propósito es hacer que un objeto de una clase esté disponible para inyección y otros objetos del proyecto también implementarán la interfaz de escucha de aplicaciones para esta clase, pasando el evento gooey started como parámetro type. Esto es necesario para que Spring Boot interprete a esta clase como un oyente eventos para un evento iniciado. Ahora implementaremos el método requerido de la interfaz. También necesitará un constructor. Este constructor tomará un objeto de recurso con una anotación de valor apuntando a un archivo llamado ventana principal punto FXML, que se agregará posteriormente al proyecto. El constructor también tomará un argumento de contexto de aplicación. Luego inicializaremos a propiedades privadas con el mismo nombre que los argumentos del constructor. Hará que ambas propiedades sean Finales. Bien, ahora que tenemos nuestras dependencias inyectadas en esta clase, implementemos el código del método de evento de aplicación. Este código se encargará de mostrar la ventana principal de nuestra billetera cuando iniciemos el programa. Así que primero vamos a crear una instancia de un objeto cargador FXML. Entonces obtendremos el objeto stage desde el evento GUI started. Para ello, agregaremos el método gets stage a la clase de evento iniciado pegajoso. Este método devolverá el objeto stage. Añadiremos un título a la billetera usando el método set title del objeto stage. Puede ser cualquier cadena que quieras. Lo pondré como cartera BYOD W. Este texto se mostrará en la barra superior de la ventana de programas. También llamará al método set scene, pasando un nuevo objeto de escena como su parámetro instanciado con un objeto devuelto por un nuevo método que creará llamado initialize FXML. Este método comenzará a declarar una variable del tipo parent llamada root. Luego dentro de un bloque try catch usaremos el método set location de la variable de cargador FXML pasando la ubicación URL de nuestra propiedad FXML. Vamos a establecer la fábrica de controladores del cargador FXML a una referencia del método good bean de la propiedad context. Esto es necesario para que el framework JavaFX reconozca las clases de controlador anotadas con la anotación Component. También estableceremos la variable raíz al resultado de llamar al método load del cargador FXML capturará una IOExcepción y la lanzaremos envuelta en una excepción de tiempo de ejecución. Devolveremos la variable raíz. Por último, en el método de no aplicación se llamará al método show del escenario, lo que provocará que la ventana se muestre en la pantalla. Ahora vamos a crear el archivo FXML, pero nos referimos a la anotación de valor de la propiedad FXML del constructor del listener. Y el archivo FXML es un tipo de archivo utilizado para codificar elementos GUI de una aplicación JavaFX. Al igual que un archivo HTML, codifica páginas web, archivos FXML y código Las ventanas de efectos Java crearán este archivo dentro la nueva ruta FXML que creará. Este directorio se ubicará dentro de la ruta de recursos. Lo llamaremos subrayado principal ventana punto FXML. Eliminemos la versión abreviada generada automáticamente. Vamos a agregar una etiqueta de panel de borde. Le agregaremos algunos atributos. Se agregará un Fx ID que permitirá hacer referencia a la etiqueta del panel de borde dentro de su clase de controlador, que se creará más adelante. Vamos a agregar algunos atributos para establecer el tamaño de la ventana. Finalmente, agregaremos algunos atributos de metal para establecer el esquema del archivo. Eso es. Ejecutemos la aplicación para ver si todo salió bien. Dentro de la pestaña Maven, vamos a hacer clic en plug-ins, Spring Boot y Spring Boot run. Genial. La primera ventana de nuestro monedero ha aparecido en la pantalla. Buen trabajo. 9. 7 Creación de nuestra primera parte 1 skillshare 2: En este video, comenzaremos a construir una prueba para la primera característica de nuestra billetera. La primera característica de nuestra billetera será la opción de crear una billetera. Más específicamente, crearemos un menú con un botón que al hacer clic, hará que aparezca un cuadro de diálogo en la pantalla. Ese cuadro de diálogo contendrá inicialmente un TextField donde el usuario definirá el nombre de la billetera y un botón Crear que al hacer clic, generará una semilla mnemotécnica aleatoria. Aprenderá lo que es la semilla mnemotécnica. En el siguiente video, crearemos todas las funciones de nuestro Wallet utilizando el enfoque de desarrollo basado en pruebas o TDD. Este enfoque consiste en crear primero una prueba de integración, que es una prueba que describe lo queremos lograr para esa característica. Después implementaremos la función y ejecutaremos la prueba hasta que pase. Durante la implementación, podemos encontrarnos con situaciones que necesitamos hacer nuevas clases o métodos que nos ayuden a lograr nuestras metas. Si ese es el caso, crearemos pruebas unitarias para estas clases fueron métodos y las implementaremos usando TDD. Al final de cada ciclo TDD, refaccionaremos nuestro código si es necesario. Veamos cómo funciona esto en la práctica. Pero primero, agreguemos algunas dependencias a nuestro proyecto. Vamos a añadir algunas dependencias relacionadas con el framework Spark. El framework Spark es un framework de pruebas en groovy, un lenguaje de programación compatible con Java. Contiene características que facilitan la construcción de pruebas, también utilizará una versión de prueba FX compatible con Spock. Test fx es un framework que proporciona características para probar aplicaciones JavaFX. Ahora, agreguemos la maravillosa versión 3.0, 0.6 a nuestro archivo POM. Y vamos a agregarle spock spring. La versión será 2.0, groovy 3.0. Su alcance será de prueba. La siguiente dependencia que se agregará es Spark Core. La versión será la misma que Spock spring. El alcance será de prueba. La siguiente dependencia será la prueba FX Spock. Su versión será 4.0, 0.16 alpha también agregará un complemento de G Maven. Bien, olvidé poner el alcance correcto y la prueba de dependencia FX. También agregaremos algunos objetivos en el plugin GI Maven. Habrá que que groovy funcione correctamente. Ahora, haremos un cambio en el archivo de propiedades de punto de la aplicación. Spring, por defecto crea un servidor web, pero no necesitaremos uno en nuestra aplicación. Por lo que debemos establecer esta propiedad en ninguna. Así que la primavera no creará un servidor web cuando arranca. Ahora crearemos nuestra primera prueba. Pero primero, eliminemos este archivo BYOD W application test, que fue generado automáticamente por el inicializador de resorte, creará un paquete en esta carpeta llamado gooey que contendrá todo nuestro usuario gráfico pruebas de interfaz. Dentro de este paquete, vamos a crear la prueba. Pero primero en el archivo xml palm dot, da clic en el botón Cargar cambios de Maven. Ahora el IDE nos permitirá crear clases groovy. Así que vamos a crear uno llamado Crear prueba de billetera. Añadiremos a esta clase una anotación de prueba Spring Boot extenderá esta clase con la clase de especificación de la aplicación. Esto es necesario para que tanto Spring Boot test fx consideren esta clase como una clase de prueba. Cada prueba de integración debe contener esta anotación y extensión. Debemos implementar el método start desde la especificación de la aplicación. También implementaremos los métodos de unidad y stop. Dentro del método init se agregará este código que es necesario para la inicialización de la prueba. Dentro del método de parada se incluirá un código necesario para detener la prueba. Dentro del método stark, debemos incluir el código necesario para mostrar la primera pantalla de nuestra aplicación. Este código será similar al código presente en la clase de escucha iniciada GUI. Así que vamos a crear una instancia de un cargador FXML pasando la URL FXML como su argumento, luego crearemos la propiedad privada FXML con la misma anotación de valor presente en la GUI comenzó clase de escucha. Groovy transforma cada método con getter establecido en una propiedad de objeto, podemos usar esta URL aquí. En lugar de obtener URL establecerá la propiedad de fábrica del controlador el contexto obtener referencia del método bean. Agreguemos el campo de contexto a la clase. Arriba. Pondrá la anotación auto cableada. Esta anotación es necesaria para que Spring Boot inyecte el objeto de contexto de aplicación desde su contenedor de inyección de dependencia a esta variable. A continuación, crearemos la variable raíz usando el método load del cargador FXML. Entonces estableceremos el título del escenario, la escena y llamaremos al método del espectáculo escénico tal como el código dentro del oyente comenzó gooey. Bien, estamos listos para trabajar en el código de nuestra primera prueba. El nombre de la prueba será debe crear billetera. La prueba contendrá los requisitos de la función que queremos implementar, utilizará la palabra clave cuándo describir las acciones que realizará el usuario de la prueba. Entonces vamos a implementarlo. El usuario dará click en un botón con el texto conocido. Después harás clic en un botón con la billetera de texto. Después en un campo de texto con un FX id de nombre. Cuando queremos hacer referencia a un ID de FX, ponemos el nombre del ID después de un signo de libra como este. Entonces el usuario escribirá las palabras billetera MyText. Después hará clic en un botón con el texto de creación. A continuación, la prueba buscará el contenido de un campo de área de texto con una identificación ética de semilla mnemotécnica. Asignará el contenido de este campo a la variable semilla mnemotécnica. Finalmente, usaremos la palabra clave entonces para definir lo que esperamos que suceda después de que el usuario realice todas las acciones dentro del bloque de viento. Esperamos que la variable semilla mnemónica contenga un valor no nulo. Para ello, solo colocamos la variable semilla mnemónica dentro del bloque entonces. Si se establece la semilla mnemotécnica, el bloque evaluará a true y la prueba pasará. De lo contrario, se evaluará como falso y la prueba no pasará. Ejecutemos esta prueba para ver qué pasa. Primero, haremos clic en Build than on build project para asegurarnos de que el IDE cargue todos los cambios que hemos realizado en el código. Después haremos clic en Test dentro de la pestaña Maven Config. *****. El IDE volvió a quejarse de Maven, arreglemos eso rápidamente. Ahora. Realicemos de nuevo la prueba. La prueba ha fallado como se esperaba. ¿Notaste que una ventana aparecía rápidamente en la pantalla durante la prueba? Muestra nuestra ventana abierta, al menos. Comprobemos los resultados de nuestras pruebas en la consola. Dice que la consulta nueva no devuelve nodos. La prueba abrió nuestra aplicación, después trató de encontrar un elemento con el texto conocido ya que no lo encontró, rápidamente falló y cerró la aplicación. En el siguiente video, aprenderemos qué es una semilla mnemotécnica. Después en el video posterior al siguiente, crearemos nuestra primera billetera y haremos que esta prueba pase. Nos vemos. 10. Semillas de Mnemonic: En este video, aprenderemos más sobre las semillas mnemotécnicas. Entonces, ¿cuál es la semilla mnemotécnica? Una semilla mnemotécnica es una frase que contiene 121-51-8201 o 24 palabras. Se utiliza para derivar todas las billeteras, claves privadas y direcciones. Las reglas de generación de semillas mnemotécnicas que usaremos se describen en la Propuesta de Mejoramiento de Bitcoin 39 o BIP 39. Muchas carteras utilizaron las reglas BIP 39 para generar semillas mnemotécnicas. Las semillas mnemotécnicas se combinan con la cadena mnemotécnica más una contraseña opcional para producir una semilla raíz representada aquí en formato hexadecimal. La contraseña opcional se conoce comúnmente como frase de contraseña, pero usaremos la palabra contraseña para simplificar. Entonces, utilizando otros algoritmos, la semilla de raíces genera claves privadas, claves públicas y direcciones, aprenderá los detalles de estas operaciones en un video posterior. Ahora, centrémonos en cómo se generan las semillas mnemotécnicas. Para generar una semilla mnemónica, primero, debemos generar una secuencia aleatoria de bits llamada entropía de longitud igual a 128 bits. Si queremos una semilla mnemotécnica de 12 palabras, 160 bits, si queremos una con 15 palabras, 192 bits, si queremos una con 18 palabras, 224 bits si queremos una con 21 palabras o 256 bits, si queremos una con 24 palabras, luego calculamos la suma de comprobación. Para ello, calculamos la longitud de entropía dividida por 32 y obtenemos el tamaño de la suma de comprobación. Entonces obtenemos los primeros bits de tamaño de suma de comprobación del hash SHA-256 de la entropía. El resultado es la suma de comprobación. La suma de comprobación se utiliza para verificar si una semilla mnemotécnica dada es válida. Anexamos la suma de comprobación al final de la entropía inicial. El resultado se divide en grupos de 11 bits. Cada grupo de 11 bits se convierte a un número 0-2047. Estos números se utilizan como índices en una lista de palabras. Las palabras correspondientes forman la semilla mnemotécnica. 11. 9 Creación de nuestra primera parte 2 skillshare 2: En este video, continuaremos implementando la función de creación de billetera de nuestra aplicación. El primer paso es agregar un botón con el texto nuevo escrito en él. Hagamos esto. Abra el archivo FXML de punto de la ventana principal. A partir de ahora, usaremos la herramienta IDE Scene Builder para crear las ventanas de nuestro proyecto. Scene Builder nos permite crear la interfaz gráfica de usuario de nuestra aplicación de forma interactiva y sencilla. Haga clic en el botón Scene Builder en la parte inferior de la pantalla. En mi caso, esta ventana apareció. Pero si no tienes instalado Java FX o Scene Builder un botón para descargarlos aparecerá en la parte superior de tu pantalla. Después de descargarlos e instalarlos, aparecerá esta ventana. Ahora agregaremos una barra de menú superior a la ventana principal. Para ello, haremos clic en los controles, luego arrastraremos y soltaremos el componente de la barra de menú a la parte superior del menú del panel de borde a continuación. Ahora tendremos una barra de menú con tres elementos de menú. Eliminemos los de edición y ayudemos. Cambiemos el menú del archivo etiquetado dos nuevos. Genial. Ahora tenemos nuestro nuevo botón. Comprobemos nuestra prueba para ver qué hacer a continuación. La siguiente acción que hará nuestro usuario es hacer clic en el botón de la billetera. Vamos a crearlo. De vuelta a la ventana principal. Añadiremos un elemento de menú dentro del nuevo menú. En este caso, ya tenemos un elemento del menú. Entonces cambiemos su etiqueta a billetera. Cuando el usuario hace clic en el botón de la billetera, debe aparecer una nueva ventana de diálogo. Vamos a implementarlo en el Scene Builder. Haga clic en el elemento del menú de la billetera. Vamos a añadir una acción a este botón. Haga clic en Código, escriba abrir crear diálogo de billetera. Si hacemos clic en el botón Texto en la parte inferior de la pantalla y verificamos el archivo FXML. Notaremos que el IDE ha agregado el atributo on action en la etiqueta de elemento de menú con el valor que acabamos de escribir. Ahora, para crear una acción para este botón necesitará crear un controlador. Pero primero, hagamos un poco de refactorización en nuestro código. Crearemos un nuevo paquete dentro del paquete BYOD W. Vamos a llamarlo gooey le transferirá los paquetes de eventos y oyeners, agregará todas las clases relacionadas con la gráfica de usuario de las aplicaciones interfaz gráfica de usuario de las aplicaciones a este paquete. De vuelta a la ventana principal, agregaremos un atributo de controlador FX a la etiqueta del panel de borde y lo configuraremos en el nuevo controlador que crearemos dentro de un nuevo paquete de controladores. Dentro del paquete gooey. Su nombre será controlador de ventana principal. Cada archivo FXML puede tener un controlador que se utiliza para definir las acciones que ocurren en respuesta a las interacciones del usuario con la ventana codificada por ese FXML. En nuestro caso, el controlador de ventana principal contendrá código que definirá acciones en respuesta a eventos en la ventana principal. Volver a la ventana principal punto archivo FXML. Cuando hacemos clic en el atributo Open create wallet dialogue y presionamos Alt más enter, el IDE mostrará la opción de crear un método dentro del controlador de la ventana principal. Haga clic en esta opción. El IDE generó automáticamente el método en el controlador de ventana principal. Eliminemos el argumento del evento de acción porque no lo necesitaremos. En este método se incluirá el código encargado de abrir el diálogo crear billetera. Cuando hacemos clic en el elemento del menú de la billetera, primero instanciaremos un objeto de diálogo de tipo botón tipo. Después estableceremos los diálogos en su propietario a la ventana del panel de borde para indicar que el diálogo pertenece al panel de borde de la ventana principal. Volver a la ventana principal punto archivo FXML. Podemos dar clic en el atributo ethics ID de la etiqueta del panel de borde, presionar Alt más Enter y crear la propiedad border pane dentro del controlador de la ventana principal. El IDE generó automáticamente la propiedad. Vamos a configurarlo en privado e incluir la anotación FXML encima de él para indicar que se refiere a un componente FXML. Después estableceremos el título del diálogo para crear una nueva cartera. Ahora, dentro de un bloque try catch instanciará un objeto cargador FXML. Pasando estos argumentos. Luego crearemos la propiedad create wallet dialogue y la propiedad context. Después crearemos un constructor para inicializar ambas propiedades. Ambas propiedades serán inyectadas automáticamente por el contenedor de inyección de dependencia Spring agregará una anotación de valor al argumento constructor create wallet dialogue pasando la ruta de un FXML archivo que creará a continuación. Luego estableceremos el contenido del dolor de diálogo al resultado de llamar al método load del cargador FXML luego capturará una IOException y la lanzaremos como una excepción en tiempo de ejecución. Por último, llamaremos al programa de diálogo y método de espera para abrir el diálogo. No olvides agregar la anotación de componentes a esta clase. Ahora, ejecutemos nuestra aplicación para ver qué tenemos hasta el momento. En la pestaña Maven dentro de plugins y Spring Boot, da clic en Spring Boot run. Tenemos nuestra barra de menú superior con el botón Nuevo y el botón de billetera. Cuando hacemos clic en el botón de la billetera, la aplicación lanza una excepción. Eso se debe a que no encontró el archivo FXML de punto de diálogo de crear billetera. Vamos a crearlo. Después de crearlo, da clic en Scene Builder. Eliminemos este panel de anclaje. Arrastre el dolor del diálogo y suéltelo aquí. Bueno. Ajustemos el tamaño de la misma. Haga clic en Maquetación. Después en el campo de altura pref tipo 500, en el tipo de campo ancho pref para 50. Luego establece el tamaño de preparación de uso en los campos min-width y min-height. Ahora agreguemos un texto de encabezado a la ventana. En el encabezado tipo de campo de texto. Dale un nombre a tu billetera y haz clic en Crear. Agreguemos un poco de relleno a su alrededor. Bueno. Ahora agreguemos un panel de cuadrícula. Arrastre y suelte este componente al dolor de diálogo a continuación. Dentro de la primera celda del panel de cuadrícula se agregará una etiqueta como esta. Y esta etiquetada contendrá el nombre de la billetera de texto. También agregaremos un campo de texto al panel de cuadrícula. Cambiemos sus coordenadas, fijemos su índice de columna en uno. Ahora agreguemos un botón al panel de cuadrícula. Cambie su índice de fila a uno y su índice de columna a uno. Cambiemos su texto para crear. Volvamos a nuestra prueba para comprobar qué más requiere. Intentará hacer clic en un componente con una identificación ética de nombre. Así que agreguemos un Fx id de nombre al campo de texto. Después de eso, intentará escribir mi billetera de texto en el campo de texto. Después hará clic en un componente con el texto Crear en él, crear con una C. mayúscula Cuando haga clic en él, la prueba buscará el contenido de un área de texto con una idea FX de semilla mnemotécnica. Así que vamos a crear esta área de texto. Arrástralo al panel de cuadrícula de abajo. Luego cambia su índice de fila a dos y su tramo de columna a dos para que el campo semilla mnemotécnico ocupe el espacio de dos columnas. Bueno. También agregaremos una etiqueta para el campo de semillas mnemotécnicas. Pero primero, agreguemos otra fila al panel de cuadrícula. Bueno. Aumentemos el índice mnemotécnico de fila de campo semilla a tres. Después arrastraremos una etiqueta al panel de cuadrícula. Ajusta su índice de fila a dos, cambia su texto a semilla mnemotécnica. Ahora agreguemos un Fx id de semilla mnemotécnica al área de texto. Ahora, ejecutemos nuestra aplicación y veamos qué pasa. Reconstruya primero el proyecto y haga clic en Spring Boot run. Genial. Pero cuando hacemos clic en Crear, no pasa nada. También debemos encargarnos del cierre de nuestro diálogo. Por ahora, haga clic en detener. El posicionamiento de estos campos me está molestando un poco. Vamos a arreglar eso. Haga clic en el botón Texto. Hemos incluido el panel de cuadrícula dentro la etiqueta de encabezado del dolor de diálogo. El lugar correcto para incluirlo está en la etiqueta de contenido. Vamos a cambiarlo. Comprobemos su aparición ahora en el Scene Builder. Genial, ahora se ve mucho mejor. En el siguiente video, continuaremos implementando la función de creación de billetera. Nos vemos. 12. 10 Creación de nuestra primera parte 3 skillshare 2: En este video, continuaremos implementando la función de crear billetera y finalmente, haremos que nuestra primera prueba de GUI pase. Para ello, agreguemos una dependencia al proyecto. Añadiremos Bitcoin, Java y biblioteca de código abierto hecha exclusivamente para este curso. Esta biblioteca contiene muchas utilidades relacionadas con Bitcoin, como métodos para generar semillas mnemotécnicas aleatorias, construir transacciones y muchas más. Para el correcto funcionamiento de esta biblioteca, debemos agregar un objetivo de complemento que copiará el archivo word list dot TXT de Bitcoin Java al proyecto durante la fase de compilación de las aplicaciones proceso de construcción. TXT sin palabras contiene todas las palabras válidas para la generación de semillas mnemotécnicas. Ahora abre el cuadro de diálogo crear cartera punto FXML. Cambiar a la vista de texto. Añadiremos un controlador a este FXML para agregar una acción al botón Crear. Así que agreguemos el atributo del controlador FX a la etiqueta de dolor de diálogo. El nombre del controlador se creará el controlador de diálogo de billetera, y lo agregaremos al paquete de controladores. Al igual que con cada controlador, le agregará la anotación de componentes. Vamos a crear la propiedad semilla mnemónica en este controlador. En el FXML, agregaremos una acción al botón Crear. Vamos a agregarlo aquí. Nombraremos la acción como crear semilla mnemónica. Y lo crearemos en el controlador correspondiente. Entonces, cuando el usuario haga clic en el botón Crear, se llamará a este método y el área de texto mostrará una semilla mnemotécnica aleatoria. Entonces estableceremos los textos de semillas mnemotécnicas al resultado del método create del servicio de semillas mnemotécnicas que creará a continuación. Inyectemos el servicio de semillas mnemotécnicas en esta clase. Ahora, vamos a crear la clase de servicio semilla mnemónico dentro del nuevo paquete llamado api dot services dentro del paquete BYOD W. Básicamente, cada clase empresarial no relacionada con la interfaz gráfica de usuario se colocará dentro del paquete API. Agreguemos el método create al servicio de semillas mnemotécnicas. Agregar la anotación de servicio a esta clase. propósito es idéntico a la anotación Componente, pero es más adecuado para las clases de servicio. Ahora, inicialicemos la propiedad mnemonic seed service en el constructor create wallet. Ahora, vamos a implementar este método porque estamos usando TDD para crear nuestra aplicación. Primero crearemos una prueba unitaria para esta clase. Vamos a crear un paquete API dentro de la carpeta test. En su interior, cree una clase maravillosa llamada prueba de servicio de semillas mnemotécnicas. Como prueba unitaria, esta clase solo necesita extender la clase de especificación de Spock. Ahora, vamos a crear una prueba llamada should return random mnemonic seed. Y esperaremos que el servicio semilla mnemotécnico devuelva un valor no nulo. Instanciemos aquí el servicio de semillas mnemotécnicas. Ejecutemos esta prueba para comprobar qué pasa. Ha fracasado como se esperaba. Implementemos este método. Para ello, usaremos el método generate random de la clase generadora de semillas mnemotécnicas de Bitcoin Java. Debemos pasar las entropías número de bits que queremos que la semilla mnemotécnica tenga como argumento a este método, vamos a usar a 56. Recuerda que una entropía de 256 bits genera una semilla mnemotécnica de 24 palabras. Por último, llamaremos al método get sentenciado a la devolución de este método y devolveremos el resultado. Al igual que con cada trabajo, una excepción comprobada, también necesitamos agregar la oración lanza FileNotFoundException a la firma del método create. Tenemos que hacer lo mismo con el método create mnemonic seed en el controlador de diálogo create wallet. Realicemos de nuevo esta prueba. Genial, La prueba ha pasado. Ahora vamos a comprobar qué sucede cuando ejecutamos nuestra aplicación. Vaya, y se produjo un error. Oh, es sobrescribir con una W mayúscula en esta etiqueta. Esta etiqueta de identificación de grupo también es incorrecta. En realidad, es solo educación de guiones de Bitcoin. Volvamos a ejecutar nuestra aplicación. Genial. Hemos generado con éxito una semilla mnemotécnica, pero quiero su texto envuelto. Vamos a arreglarlo. Vamos al diálogo crear cartera punto FXML. En el Generador de escenas, haga clic en el área de texto y haga clic en la casilla de verificación El texto de Envolver. Volvamos a ejecutar el proyecto. Bien, mucho mejor. Ahora, hagamos todas nuestras pruebas. Genial. Todos han pasado. 13. 11 Creación de nuestra primera parte 4 skillshare 2: En este video, vamos a desarrollar aún más nuestras aplicaciones crean función de billetera. Se agregará un botón OK y un botón de cancelación al diálogo de creación de billetera. Cuando el usuario haga clic en el botón Aceptar, se creará su billetera y el nombre de las billeteras aparecerá en la parte superior de la pantalla. Cuando haga clic en el botón Cancelar, el diálogo simplemente se cerrará. También agregaremos una restricción al botón Okay para que se deshabilite por defecto y solo se habilite cuando se cumplan los campos de nombre y semilla mnemotécnicos. Finalmente, agregaremos un campo de contraseña opcional para que el usuario solo pueda acceder a su billetera y realizar transacciones con ella después de proporcionar la contraseña correcta. Agreguemos estas nuevas características primero en nuestra prueba de creación de billetera. Primero, agregaremos un clic en la acción del botón Aceptar. Entonces esperaremos que el título escénico sea igual al nombre de nuestra aplicación dash el nombre de nuestra billetera, que es mi billetera de prueba. Ahora vamos a crear la propiedad de escenario. Lo inicializaremos en el método start. Ahora, vamos a crear otra prueba para verificar qué sucede cuando el usuario intenta hacer clic en el botón Cancelar. Para ello, vamos a crear una prueba con el nombre debe cancelar la creación de monedero. Por lo que esperamos que cuando el usuario haga clic en la nueva billetera y cancele, no se lanzará ninguna excepción. Realicemos estas pruebas para ver qué pasa. Las pruebas han fallado como se esperaba. Implementemos estas características. Ir al cuadro de diálogo crear cartera punto archivo FXML. Haga clic en el panel de diálogo en el lado izquierdo. Después agrega un botón OK y este campo de tipos de botón. Haga clic en más, luego agregue un botón de cancelar. Ahora agregaremos el campo de contraseña. Pero primero, agreguemos otra fila en el panel de cuadrícula. Ahora vamos a mover el nombre, etiqueta y el campo a la primera fila. Después agregaremos una etiqueta de contraseña y un campo de contraseña en la siguiente fila. También agreguemos una idea Fx de contraseña al campo de contraseña. Ahora, cambiemos texto del encabezado del diálogo a lo siguiente. Mientras estamos en ello, hagamos que el campo semilla mnemotécnico no sea editable. Esta es una medida de seguridad porque no queremos que el usuario cambie su semilla mnemotécnica accidentalmente. Cambiar a la vista de texto. Añadiremos algunos cambios a estos botones, etiquetas en el botón Bien, agregaremos una idea de Fx de bien. El botón Cancelar borrará su contenido y agregará una idea de Fx de cancelar. También agregaremos el valor de cancelado cerca de los datos del botón Atributo. También agregaremos la cadena cancel al atributo text. Esto es necesario porque cuando usamos el botón de cancelación predeterminado, su texto se traduce al idioma de la computadora, y no queremos eso. Ahora, hagamos algunos cambios en el controlador de crear diálogo. Se le agregará un método llamado inicializar. Pero primero, volvamos a su FXML y agreguemos un Fx id de dolor de diálogo a la etiqueta de dolor de diálogo. Ahora, agreguemos las propiedades con un FX ID al controlador. Lo hará con la contraseña de propiedades llamada dolor de diálogo, OK y Cancelar. Ahora volvamos al método inicializado. Este método se ejecutará después de la inicialización del diálogo. Incluirá código ahí para definir las acciones de cada botón. Primero, definiremos la acción del botón Cancelar. Cuando un usuario hace clic en él, el diálogo se ocultará. Entonces llamaremos al Método de Botón de Búsqueda del dolor de diálogo pasando el botón de cancelar como argumento. Después le agregaremos un controlador de eventos, pasando el argumento action y una callback que llamará al método hide de la ventana de dolores de diálogo. Haremos lo mismo con el botón Bien. Pero llamaremos al método create wallet en la devolución de llamada en su lugar. Vamos a incluir el mismo código para ocultar la ventana cuando el método create wallet por ahora y ejecutar la aplicación para ver qué pasa. Cuando hacemos clic en el botón Cancelar, el diálogo se esconde. Lo mismo sucede cuando hacemos clic en el botón Bien. Bueno. Pero cuando hacemos clic en la X del lado del diálogo, no pasa nada. Vamos a arreglar eso. Vaya al controlador de ventana principal. Habrá que incluir el siguiente código para cerrar la ventana de diálogo cuando hagamos clic en el botón X. Ahora, ejecutemos la aplicación e intentemos de nuevo. Bien, eso lo arregló. Cambiemos también el método de show y wait llamado al diálogo para simplemente mostrar que simplifica un poco las cosas. Ahora, vuelva a ejecutar la aplicación. Todo sigue funcionando como se esperaba. Pero hay otro tema con el diálogo. Permite la creación de billeteras sin nombre y semilla mnemotécnica. Queremos que cada billetera tenga un nombre y una semilla mnemotécnica. Por lo que necesitamos desactivar el botón Bien si uno no se cumple. Arreglemos esto. Vaya al controlador de diálogo de creación de billetera. Ahora, vamos a crear una propiedad privada de tipo Boolean binding llamada todas las entradas requeridas están llenas. Estableceremos esta propiedad en el método inicializado con el siguiente código. Aquí usaremos una clase anónima Java que extiende el enlace booleano. Después inicializaremos la clase con el método bind, pasando como argumentos las propiedades name y mnemonic seed text. Entonces en el método compute value se incluirá un código que devolverá true solo si los campos name y mnemonic seed no están vacíos. Ahora, crearemos un método getter para esta propiedad. Finalmente, llamaremos al método de propiedad para discapacitados en el botón Okay. Entonces llamaremos a bind en el resultado y pasaremos el get all required inputs are full method calling the method on it. Hagamos un pequeño arreglo en este método primero, debe devolver un enlace booleano. Y vamos a quitar esto, a buscarlo. Bueno. Ahora volvamos a ejecutar nuestra aplicación. Bien, el botón Bien está deshabilitado por defecto. Si tecleamos algo en el campo de nombre de billetera, permanece deshabilitado. Pero cuando hacemos clic en el botón Crear, se habilita. Genial. Realicemos nuestras pruebas de nuevo. Eso debería crear la prueba de billetera ha fallado porque aún no habíamos implementado el código para cambiar el título de la aplicación. Hagámoslo en el siguiente video. 14. 12 Creación de nuestra primera parte 5 skillshare 2: En este video, implementaremos una función que hará que la Aplicación Cargue la billetera y muestre su nombre en el título de la aplicación. Después de que el usuario crea, la billetera. Crearemos código que será útil más adelante cuando queramos mostrar otras características de billeteras como direcciones en la pantalla. Después de implementar esta característica, esta prueba pasará porque el título de la etapa será igual al espacio de billetera BYOD W, espacio de tablero, el nombre de las billeteras. Entonces vamos a implementarlo. Primero. Iremos al controlador create wallet. Entonces en este método, se creará una Wallet utilizando un nuevo servicio llamado create wallet service y un método llamado create. Pasaremos el nombre de las billeteras, la contraseña y la semilla mnemotécnica al método. Ahora vamos a crear la clase de cartera. Vamos a añadir un nuevo paquete dentro de BYOD W, llamarlo dominios. En su interior se agregará un nuevo registro Java llamado wallet. Por ahora, solo agregaremos un atributo de cadena llamado name a este registro. Un registro Java es una característica reciente del lenguaje. Cada atributo record tiene un getter incorporado y un constructor, así que no necesitamos agregarlos. Ahora, importe el registro de billetera al controlador de diálogo de creación de billetera. Ahora, inyectaremos el servicio create wallet en esta clase. Y crearemos esta clase dentro del paquete de servicios API. Se agregará la anotación de componentes a esta clase. Inyectemos este servicio en el constructor de esta clase. Ahora, crearemos el método create dentro del servicio create wallet. Por ahora, solo devolveremos una nueva billetera pasando el nombre como su parámetro al controlador de diálogo Crear billetera. Ahora que hemos creado la billetera publicaremos un evento que tomará como parámetro la billetera creada. Este evento será escuchado por una clase para que cuando el usuario cree una billetera, el oyente actualice la billetera actual cargada por la aplicación. Inyectemos el contexto de la aplicación en esta clase. Ahora, vamos a crear el evento de billetera creado dentro del paquete de eventos. Luego llamará al súper constructor pasando el controlador de diálogo create wallet. Y estableceremos un nuevo campo de wallet, asignándole el argumento constructor wallet también incluirá un getter para este campo. Ahora, vamos a crear un oyente para este evento llamado creado listener de billetera. Y lo crearemos dentro del paquete de oyentes. Implementará la clase de escucha de aplicaciones con el evento wallet creado como parámetro. Luego implementará el método en evento de aplicación. Se llamará a un método de un nuevo servicio llamado actualizar el servicio de billetera actual. Este método llamado update toma como parámetro la cartera de eventos. Inyectemos este nuevo servicio en esta clase y creemos el servicio. Lo agregaremos dentro de un nuevo paquete de servicios. Dentro del paquete pegajoso. A continuación se creará el método de actualización en él. También le agregaremos una anotación de Servicio. Por ahora, el método de actualización solo establecerá el nombre de la billetera actual en el nombre de billetera recién creado. Ahora, vamos a crear un nuevo paquete dentro de BYOD W llamado observables. Dentro de este paquete se creará la clase de billetera actual. Volver al servicio de billetera Update Current instanciará la billetera actual en su constructor. En la clase actual de monedero se incluirá la anotación Componente. Esta clase representará la cartera actual cargada por la aplicación. Cada cambio que realice la aplicación a esta instancia de clase aparecerá en la interfaz gráfica de usuario de las aplicaciones. Lo incluimos en un paquete llamado observable, porque cada propiedad de esta clase será inobservable. Y observable es un tipo de objeto en el que cada cambio de estado puede ser escuchado, promulgado por otros objetos. La primera propiedad observable que le agregaremos es el nombre. Tendrá el tipo de propiedad string simple. Este tipo implementa la interfaz observable y desencadena un evento de cambio cuando su valor de cadena cambia. Lo vamos a instanciar aquí. Y crearemos un getter para este campo. Intellij idea identificó que es un observable y creó dos getters. Uno para la propiedad llamada name property y el otro para el valor de propiedad llamado getName también creará un setter para este campo para establecer el valor de la propiedad name. Hagamos que este campo sea definitivo. También hará una prueba para esta clase de servicio de creación de billetera. Deberíamos haber creado la prueba antes de implementar este método, ya que estamos usando TDD. Pero considerando vamos a incrementar esta funcionalidad de métodos donde se perdona. Vamos a crear la prueba. Ahora. Primero crearemos una propiedad para el servicio create wallet e instanciaremos dentro del método de configuración que se ejecuta antes de cada prueba. Entonces crearemos una prueba llamada debería crear billetera. Dado tenemos un nombre, una contraseña, y una semilla mnemotécnica. Cuando llamamos al método create desde el servicio create wallet con estos parámetros. Entonces esperaremos que el nombre de la billetera sea igual a la variable name. Vamos a hacer la prueba. La prueba ha pasado. Ahora, recapitulemos lo que hemos hecho hasta ahora. Cuando el usuario haga clic en el botón Aceptar, se llamará al método de crear billetera desde el controlador de diálogo de crear billetera y el servicio de billetera creará la billetera. Para ello, utiliza el método create, tomando el nombre, la contraseña y la semilla mnemotécnica que el usuario haya elegido. Por ahora, este método sólo devuelve una nueva cartera con su nombre. Luego pasamos la billetera creada a un nuevo evento de billetera creado y publicamos este evento. Cuando esto sucede, activará el método de escucha de billetera creado en el evento de aplicación. Recibirá el evento de wallet creado como su parámetro. Debemos agregar la anotación de componente a esta clase e inyectar el servicio de billetera actual de actualización en su constructor. Por lo que el método de evento de aplicación llamará al método de actualización desde el servicio de billetera actual de actualización, pasando la billetera del evento como su parámetro. Por último, el método de actualización. Estableceremos el nombre de la billetera actual el nombre de la billetera recién creada. Ahora, volvamos al controlador de ventana principal. Aquí se creará un método inicializado que se ejecutará antes de que aparezca la ventana principal de la aplicación. En su interior, agregará un oyente a la propiedad actual de billetera. Inyectemos primero la cartera actual en esta clase. Dentro del método de escucha de anuncios pasará una devolución que tomará tres parámetros y valor observable y antiguo, y un nuevo valor en el cuerpo de devolución obtendrá la etapa de Windows y asignarlo a la variable de etapa. Debemos lanzar su tipo a escenario. Después estableceremos su título en BYOD W wallet space, dash space, new value. La nueva variable de valor contiene el nuevo valor del nombre de la cartera actual. Siempre que cambie el nombre de la billetera actual, este cambio será escuchado por esta devolución de llamada y el título de la etapa también cambiará a la oración que acabamos de decir. Ejecutemos la aplicación para verificar si esto funciona. Crearemos una nueva billetera con la prueba de nombre, luego una semilla mnemotécnica y haremos clic, Bien, genial, funcionó. El título de la ventana cambia a BYU OWL una prueba de guión. Vamos a crear otra cartera con un nombre diferente para ver qué pasa. Como se esperaba. Se ha cambiado para que coincida con la billetera recién creada. Ahora, hagamos todas nuestras pruebas. Genial. Todas las pruebas han pasado. Buen trabajo. 15. 13 Creación de nuestra primera parte 6 skillshare 2: En este video, comenzaremos a implementar una función que nos permitirá crear direcciones que serán utilizadas posteriormente para recibir Bitcoins. Lo primero que haremos es crear la pestaña Recibir. Esta pestaña contendrá las direcciones derivadas de nuestra billetera. Así que ve a la ventana principal punto archivo FXML. En el Constructor de escenas se incluirá una caja V en el centro del panel de borde. Dentro de la caja V se incluirá un panel de pestañas. Eliminará la segunda pestaña que se creó, automáticamente. Cambiar el texto de las pestañas restantes para recibir. Dentro del menú de configuración de VBox se establecerá la altura pref a 300. Dentro de la pestaña Recibir se incluirá un panel de cuadrícula. Por alguna razón, no podemos incluir un panel de cuadrícula en una pestaña usando el Generador de escenas. No hay problema. Lo haremos usando el editor de texto. En cambio. Incluiremos una etiqueta. Su texto será igual a la dirección de recepción. En su interior agregará algunas etiquetas para establecer sus márgenes. Ahora, incluiremos un campo de texto. No será editable. Tendrá 350 ya que es ancho pref. Y su índice de columnas será igual a uno, incluirá las mismas etiquetas de margen de panel de cuadrícula que usemos anteriormente. El constructor de escenas ya no funciona debido al panel de cuadrícula que hemos incluido en la pestaña. No hay problema. Veremos cómo se ve la aplicación ejecutándola. Genial, nuestra cartera ya está lista para recibir una dirección en este nuevo campo que acabamos de crear. Dentro de la prueba de creación de billetera incluirá un código para verificar si se creó una dirección y se insertó en el campo de dirección de recepción después de crear la billetera. Entonces, después de que la prueba haga clic en el botón Aceptar, dará clic en la pestaña Recibir. Y la prueba buscará el contenido del campo de dirección receptora y lo almacenará en la variable address. Entonces la prueba afirmará, si no se conoce la dirección, vamos a ejecutar la prueba para ver qué pasa. La prueba ha fallado como se esperaba. Ahora, hagamos un poco de refactorización y nuestro archivo FXML de la ventana principal. Vemos ahora que nuestro archivo FXML principal es cada vez más grande, es mejor crear un nuevo archivo FXML solo para la pestaña de recepción, que son ventana principal a la que se referirá más adelante. Así que vamos a crearlo. Lo llamaremos Recibir tab dot FXML copiará todo el contenido de la pestaña al punto de pestaña Recibir FXML. El único cambio que haremos es a la etiqueta de tabulación. Lo cambiaremos a f x raíz de colon. Después usaremos la clase tab como el atributo type. También necesitamos incluir el atributo Meta XML y S colon FX. Ahora importaremos las otras etiquetas. Volver a la ventana principal punto FXML eliminará la etiqueta de tabulación y todo su contenido. Incluirá la etiqueta Receive tab controller, que creará ahora. Lo crearemos dentro del paquete de controladores. Y vamos a importarlo dentro de la ventana principal punto FXML. Volver al controlador de pestaña Recibir agregará la anotación de componente a esta clase. Crearemos un constructor pasando un recurso con una anotación de valor apuntando a la pestaña Recibir archivo FXML también pasará el contexto de la aplicación. Aquí configuraremos una nueva instancia de cargador FXML con parámetros similares a los que hemos usado para los otros controladores. Entonces pondremos su controlador a esto. También estableceremos su ruta a esto. Entonces llamaremos al método de carga en él. Bien, necesitamos hacer una cosa más para que funcione. Dentro de la clase de oyente iniciado gooey, agregue el siguiente código aquí. Este código es necesario para decirle a Java FX cómo construir componentes personalizados, como el controlador de pestañas Recibir cuando lo ve dentro de los archivos FXML. Este código hará que Java FX use el contexto para obtener el método bean para construir un componente cuando ve una etiqueta de controlador de pestaña Receive. Entonces, siempre que Java FX necesite construir una etiqueta de controlador de pestañas Recibir, usará la clase de controlador de pestañas Recibir para construirla. Para otras etiquetas, usará el generador Java FX predeterminado. Eso es. Ahora Java FX sabe cómo construir nuestra nueva etiqueta FXML personalizada. Ejecutemos nuestra aplicación para verificar si todo va bien. ***** y se produjo un error. Es decir que el controlador raíz no es una instancia de tabulación. Sé cómo arreglarlo. Debemos hacer que el controlador de pestaña Recibir extienda la clase TAP. Ahora, veamos si funciona. Bien, está funcionando igual que antes. Entonces, cuando creamos una nueva billetera, esperamos que el campo de dirección de recepción se llene con la nueva dirección de Bitcoin. En el siguiente par de videos, entenderemos el proceso de derivar una dirección de Bitcoin e implementar esta función en nuestra billetera. Verás, sí. 16. Direcciones de Bitcoin y billetera de alta definición: En este video, aprenderemos sobre billeteras HD y las direcciones de Bitcoin. Entonces, ¿qué es una dirección de Bitcoin? Una dirección bitcoin es una palabra que codifica una clave pública, el hash de una clave pública o un hash de script. Se utiliza para recibir bitcoins en una transacción. Para recibir Bitcoins a través de una transacción de Bitcoin, muestras tu dirección a otra persona que esa persona pueda enviar bitcoins a tu dirección. Existen varios tipos de direcciones Bitcoin y las reglas para generarlas están en muchos VIP, como VIP, VIP 3d2 y BIP 44. Hablemos ahora de carteras HD. Las carteras Hd son sinónimo de carteras deterministas jerárquicas. Son jerárquicos porque están compuestos por muchos niveles de claves, y son deterministas porque una sola semilla siempre generará las mismas direcciones y claves privadas. Y HD Wallet es un tipo de wallet donde a partir de una sola semilla se utilizan pads de derivación para derivar claves privadas, claves públicas y direcciones. Las especificaciones de las billeteras Hd se definieron originalmente en BI P32 con otros BIP que se extienden en esa especificación. Ahora vamos a recapitular una diapositiva de nuestra última presentación ppt. En esta presentación aprendimos a generar una semilla mnemotécnica. Y mencionamos que al combinar una semilla mnemotécnica con una frase de contraseña opcional, podríamos generar una semilla raíz usando el algoritmo P vk df two. A partir de esa semilla raíz, podríamos generar claves privadas, claves públicas y direcciones. En esta presentación, profundizaremos en los detalles de esa última parte sobre cómo se generan claves y direcciones privadas y públicas a partir de una semilla raíz. Entonces, comenzando con una semilla raíz, que tiene 512 bits de tamaño, aplicándole el algoritmo hash HMAC SHA-512, obtenemos la clave maestra, que también tiene 512 bits de la clave maestra. Al aplicar la función CKD, que significa derivación de claves secundarias, podemos obtener diferentes claves extendidas usando diferentes índices como parámetros. Si n es el índice para esa función, que n puede variar 0-2 a la potencia de 32 menos uno. Cada clave extendida puede generar claves más extendidas mediante el uso de la función CKD y así ser el padre de muchas teclas secundarias. Este esquema de derivación permite la formación de un árbol de claves con un número indefinido de generaciones. Veamos más detalles sobre las funciones de la ERC. Hay dos tipos de llaves extendidas. Pueden ser claves privadas extendidas o claves públicas extendidas. Y la clave privada extendida cuya versión serializada comienza con x PRV, u otra letra más PRV se genera usando la función privada CKD. Si el paso índice a esa función es igual o mayor que dos a la potencia de 31, entonces es una derivación endurecida. Y decía que la clave privada extendida generada es un hijo endurecido. Las claves endurecidas tienen características de seguridad adicionales que explicaremos en resumen, es posible generar una clave pública extendida mediante el uso de la función pública CKD. Asistía a llaves públicas cuando se serializaba, comenzar con x pub, u otra carta más pub. También es posible generar una clave pública extendida a partir de otra clave pública extendida mediante el uso de la función pública CKD, dos derivaciones no son posibles. Generar una clave privada extendida a partir de una clave pública extendida y una clave pública extendida endurecida a partir de una clave pública extendida. Entonces, ¿cómo obtenemos de las claves extendidas a las direcciones? Comenzando con una clave privada extendida, extraemos una clave privada de ella. Una clave privada es parte de una clave privada extendida. Por lo que esta extracción es una operación sencilla. Luego, mediante una operación llamada multiplicación de curva elíptica, generamos una clave pública a partir de una clave privada. Finalmente, al hash y codificación de la clave pública, obtenemos una dirección Bitcoin. Existen diferentes tipos de hash y codificación de claves públicas para producir diferentes tipos de direcciones. Aprenderemos más sobre estas operaciones en los próximos videos. También utilizamos claves privadas para producir firmas de transacciones, para transferir Bitcoins a otras direcciones. Las firmas de transacción se producen utilizando el algoritmo de firma digital de curva elíptica o ECDSA. También puede generar direcciones con una clave pública extendida. Eso se hace extrayendo la clave pública de ella. Entonces se genera una dirección bitcoin a partir de la clave pública a través del hashing y la codificación, como se explicó anteriormente. Recuerda que una clave pública no se puede convertir en una clave privada. Por lo tanto, no se puede utilizar para firmar transacciones y transferir Bitcoins. Ahora, entendamos el concepto de rutas de derivación, comenzando por la clave maestra, que tiene la profundidad de cero en un árbol de claves extendidas. Al derivar una clave extendida pasando cero como argumento a una función CKD, obtenemos una clave extendida con una profundidad de uno. Repitiendo el proceso con la clave extendida recién generada, obtenemos una clave extendida con una profundidad de dos. Entonces podemos repetir el proceso, pasando uno como índice y obteniendo una clave extendida con una profundidad de tres. De esta última clave extendida, podemos extraer una clave pública y una dirección. Se dice que esta dirección tiene una ruta de derivación de cero slash zero slash one porque estas fueron el índice se usa para derivar la clave extendida que generó esa dirección. Aplicando el mismo razonamiento. En este otro ejemplo, obtenemos una dirección con una ruta de derivación de una slash zero slash two. Este otro ejemplo muestra que se pueden usar otros números como índices para funciones CKD en cualquier clave extendida en un árbol de claves, permitiendo la generación de un número casi infinito de rutas de derivación y direcciones. Este otro ejemplo muestra la generación de un hijo endurecido mediante el uso de una sola comilla después del índice, podemos representar índices que generan hijos endurecidos en una ruta de derivación. Cero seguido de una sola cita, representa el primer índice endurecido, que es de dos a la potencia de 3011, seguido de una sola cita es el segundo índice de endurecimiento y así sucesivamente. Esta notación se utiliza para facilitar la descripción de una ruta de derivación de manera que podamos usar números pequeños para describirlos. Es importante agregar eso. Para gastar Bitcoins desde una dirección, es necesario producir una clave privada con la misma ruta de derivación utilizada para derivar esa dirección. Por lo tanto, puede utilizar las funciones públicas de CKD para producir claves y direcciones públicas extendidas. Pero para gastar fondos de esas direcciones, debes usar funciones privadas CKD para producir claves privadas extendidas y claves privadas. Otra característica de las billeteras HD y son caminos de derivación es su relación de función de muerte. cada nivel en un árbol de claves se le asigna una función. Bi P32 define la profundidad, uno representa cuentas profundidad dos cadenas diferentes y profundidad tres direcciones diferentes. Bip 44 vino con diferentes definiciones que son más utilizadas hoy en día en la mayoría de las billeteras HD. De acuerdo a estar a 44 profundidad una llaves extendidas endurecidas representan diferentes propósitos. Profundidad para endurecer llaves diferentes tipos de monedas, profundidad tres llaves endurecidas, cuentas diferentes. profundidad para define si las direcciones descendentes se van a usar para el cambio no son de manera booleana y la muerte cinco representa direcciones diferentes. Para entender mejor cómo funciona eso en la práctica, veamos algunos ejemplos de caminos de derivación y sus funciones. Y abordado con una ruta de derivación de 84 cotizaciones slash slash zero slash zero slash zero tiene un propósito para encontrar y BIP A14. Vip 84 define que las direcciones con un propósito de 84 deben ser P2 WP k h direcciones, que significa pagar para presenciar direcciones hash de clave pública. Hablaremos de diferentes tipos de direcciones en detalle en los próximos videos. Pero en definitiva, P2, WP k, h, aka segue, las direcciones nativas son el tipo de direcciones más comunes en las billeteras modernas más actualizadas. Esta dirección también tiene un tipo de moneda de cotización cero, lo que significa que es una dirección de Bitcoin. También tiene una cuenta de cero, lo que significa que forma parte de la cuenta del primer usuario. Ha cambiado. El índice se establece en cero, lo que significa que no es una dirección de cambio. Por último, su índice de direcciones es cero, lo que significa que son los primeros usuarios que reciben dirección. El siguiente ejemplo tiene una ruta de derivación similar al ejemplo anterior, excepto que su índice de direcciones es uno. Por lo que es la segunda dirección de recepción nativa de Bitcoin segue de la cuenta del primer usuario, aplicando la misma justificación. El tercer ejemplo es la primera dirección de cambio nativo de Bitcoin segue de la cuenta del primer usuario. El índice uno en profundidad cuatro indica que es una dirección de cambio. El último ejemplo es similar al primero, excepto que su propósito es 49 entre comillas. Vip 49 define que las direcciones con ese propósito deben ser P2 WP k-th anidadas en direcciones P2 SSH. Si eso suena complicado, no te preocupes, conoceremos detalles al respecto en los próximos videos. Ahora, hagamos una descripción general de las funciones de HD Wallet. Con las billeteras HD, podemos generar fácilmente un número casi infinito de direcciones a partir de una sola semilla. Esto es genial ya que podemos evitar reutilización de direcciones y la pérdida de privacidad. Las billeteras HD también permiten la estructura de cuentas múltiples donde la clave privada extendida principal tiene acceso a los fondos de las claves de sus hijos, pero los niños pueden transferir los fondos de los padres. Este esquema puede ser útil para casos como dueños de empresas que tienen acceso a llaves infantiles desde los departamentos de su compañía. Otra característica útil que permiten las billeteras HD es la creación de billeteras solo para relojes cuyas direcciones se pueden generar y sus fondos auditados utilizando solo claves públicas extendidas, pero donde ningún fondo puede ser movido ya que no se pueden firmar transacciones. Otra característica de HD Wallet es la posibilidad de generar otras direcciones de criptomonedas a partir de la misma semilla mnemotécnica. Una lista de diferentes índices de tipo de moneda se describe en el slip 44, un sistema de propuestas tipo BIP de Satoshi labs, la empresa responsable del truss o billetera. Otra característica que tienen las billeteras HD es que sus direcciones y claves privadas pueden reconstruirse con sus semillas y rutas de derivación. Esto le permite importar una semilla mnemotécnica y una frase de contraseña en una billetera compatible para recuperar todas sus direcciones y claves privadas. compartimentación de seguridad es otra característica agradable de las billeteras HD. Si una clave privada extendida se filtra por accidente, eso afectaría solo a los fondos bloqueados en direcciones que descienden de la clave filtrada. Los fondos encerrados en las llaves de los padres o hermanos estarían seguros. Por último, las billeteras HD facilitan generación de una organización de diferentes tipos de direcciones de Bitcoin. Ahora veamos por qué son necesarias las llaves endurecidas. Durante el desarrollo de HD Wallet, se descubrió que si una clave pública extendida y una clave privada secundaria no Hodgkin del siguiente nivel, esto equivaldría a una fuga esto equivaldría a aparente clave privada extendida. Esto podría llevar a la pérdida de fondos por cada dirección desciende de la clave pública extendida filtrada. De ahí que se creara la derivación del indulto para evitar que ese exploit ocurriera a cuenta y profundidades más bajas. Por último, discutamos cómo implementaremos el esquema de derivación de direcciones en nuestra billetera. Utilizaremos la ruta de derivación 84 cotizaciones slash slash slash zero slash zero slash zero para generar nuestra primera dirección de recepción. Después de recibir Bitcoins, la siguiente dirección de recepción se cambiará aumentando el índice de direcciones en uno. Por lo que las siguientes direcciones receptoras tendrán índices de direcciones de 123 y así sucesivamente. Hacerlo nos impide usar la misma dirección para recibir Bitcoins más de una vez. Utilizaremos la ruta de derivación 84 cotizaciones slash, slash, slash one slash zero para generar nuestra primera dirección de cambio. Después de enviar Bitcoins y recibir un cambio, la siguiente dirección de cambio se cambia aumentando el índice de direcciones en uno. la misma manera lo haremos para recibir direcciones. Puede preguntar por qué es importante evitar la reutilización de direcciones por dos razones principales. Primero, al hacer eso, aumentamos nuestra privacidad. Al hacerlo, si un tercero descubre que una dirección nos pertenece, esa información no se replicará a otras direcciones que usemos. La otra razón es la seguridad. Si por alguna razón se filtra la clave privada de una dirección eso afectará únicamente a esa dirección. el proverbio que dice, Aquí se aplica el proverbio que dice, no pongas todos tus huevos en una sola canasta. Dicho esto, implementaremos el esquema de derivación generando primero la clave pública extendida con una ruta igual a 84 comillas slash zero slash zero slash zero slash zero para recibir direcciones. Y la clave pública extendida con una ruta igual a 84 comillas slash slash zero slash one para cambiar direcciones. Después vamos a derivar sus hijos las claves públicas extendidas y direcciones. Al hacerlo, generaremos todas las direcciones que necesitemos sin exponer ninguna clave privada a la memoria. Por lo que nuestra principal política de seguridad es evitar exponer semillas y claves privadas a la memoria tanto como sea posible. Nuestras claves privadas se derivarán solo al firmar transacciones utilizando los mismos pads de derivación utilizados para producir las direcciones desde las que dichas transacciones están gastando Bitcoins. 17. 15 Creación de nuestra primera parte 7 skillshare 2: En este video, vamos a crear las claves públicas extendidas que son monedero necesitará para crear direcciones. Como vimos en el último video, nuestras billeteras tendrán inicialmente claves extendidas, que serán la clave extendida para direcciones de recepción de segmentos, y la clave extendida para direcciones de cambio de segue. Primero, arreglemos algunos problemas con nuestras pruebas de GUI. Si intentas ejecutar la prueba de crear billetera, ahora, verás que funcionará. Esto se debe en parte a una instanciación prematura de nuestra nueva clase de controlador de pestaña Recibir. Para solucionarlo, cree un nuevo paquete llamado Config dentro del paquete de prueba BYOD W. Entonces crea una nueva clase llamada test lazy siendo una configuración IP en ella. Esta clase implementará el postprocesador bean factory implementará este método requerido con este código. Este código hará que cada clase durante las pruebas se inicialice perezosamente. Hay otra pieza de código que debemos agregar en nuestra prueba de creación de billetera para que funcione. Añadiremos al cargador FXML en el método start, la misma fábrica de constructores que hemos establecido en nuestra clase de escucha iniciada GUI. Ahora vamos a ejecutar nuestras pruebas GUI. Genial. Ahora las pruebas están funcionando. Vemos que solo ellos deberían cancelar las pruebas han pasado y el otro todavía tenemos que hacerlo pasar. Ahora, procedamos a agregar las claves públicas extendidas a nuestra billetera. Lo primero que haremos es ajustar nuestra prueba de crear servicio de billetera pasará una semilla mnemotécnica válida a esta variable. Puedes obtenerlo en la página Proyecto y Recursos. Después verificaremos si la cartera creada tiene claves públicas extendidas. Afirmar si tiene dos claves públicas extendidas, ya que cada billetera tendrá una clave pública extendida para recibir direcciones y una clave pública extendida para direcciones de cambio. Ahora, agregaremos una lista de claves públicas extendidas al registro de billetera. Vamos a crear nuestra clase extendida de clave de pub. Tendrá una llave y un tipo. Vamos a agregarlos a un constructor. Ambas propiedades tendrán un getter. Ahora crearemos una clase de configuración de direcciones. Primero, vamos a crear un nuevo paquete de configuración dentro del paquete API. Después crearemos la clase de configuración de direcciones en ella. Añádele la anotación Configuración. Esta anotación es necesaria para que Spring Boot inicialice todos los objetos definidos en esta clase durante el inicio de la aplicación. Ahora vamos a crear una clase de dominio llamada address config. En realidad, va a ser un disco. Tendrá un tipo de dirección y la ruta de derivación. Luego crea una enumeración llamada address type en el mismo paquete. Tendrá dos tipos, segmento y segue con cambio de subrayado. Ahora volvamos a la clase de configuración de direcciones. Crearemos un haz para nuestra dirección de segmento. En Spring Boot, un bean es solo un objeto que se puede inyectar en otras clases de proyecto. Instanciará este bean con estos parámetros. Y agrega la anotación Bean a este método. Pasando la cadena de segmento como su parámetro duplicará este método y lo modificará para que sea nuestra configuración de dirección de cambio, cambiará el parámetro Bean annotation para segue change. El nombre del método será segue change config. El tipo de dirección será seg cambiaría. Y la ruta de derivación tendrá un índice de cambio de uno. Ahora, usaremos estas configuraciones en nuestro servicio de creación de billetera. Así que vamos a inyectar una lista de configuraciones de direcciones en esta clase. Al hacerlo, Spring Boot identifica automáticamente que hay dos beans con el tipo de configuración de dirección, e inyectará ambos en esta lista. Ahora, en el método create se creará una variable semilla mnemónica. Primero, cambiaremos el parámetro del método de semillas mnemotécnicas a la cadena de semillas mnemotécnicas y luego instanciaremos un objeto semilla mnemónico pasando la cadena de semillas mnemotécnicas como su parámetro. Luego crearemos una clave maestra, que es un tipo de clave privada extendida. Para ello, llamaremos al método mnemotécnico seed a master key y pasaremos la contraseña y esta constante como sus parámetros. Pero primero, tenemos que actualizar nuestra versión Bitcoin Java a 0.3, 0.0 en el archivo POM. Vamos a hacerlo. Ahora. Haga clic en Load Maven vuelve a cambiar al método create. Ahora nos permite importar la constante principal del prefijo neto, pasará su prefijo privado como parámetro. Ahora agreguemos este código, entonces voy a explicar qué hace a continuación. Este código comienza a convertir la lista de configuración de direcciones en una transmisión. En Java ocho o superior, los flujos se utilizan para aplicar operaciones funcionales a una colección de datos. En este caso, cada configuración de dirección de la lista se está pasando a esta función lambda, que utilizará el servicio de clave pub extendido que creará junto para devolver un objeto de clave pub extendido. Cada clave de pub extendida devuelta se recogerá en una lista que se almacenará en la variable de claves de pub extendidas, luego pasará la lista de claves de pub extendidas a la billetera devuelta. Ahora, inyectemos el servicio extendido de llaves de pub en esta clase. Tendremos que crearlo. Ahora podemos agregarlo al constructor. Ahora creará su método de creación. Devolverá una llave de pub extendida. Siguiendo el TDD. Es momento de crear una prueba para este método. Vamos a hacerlo. Lo creará dentro del paquete API de prueba. Debe extender la clase de especificación. Instanciemos el servicio extendido de llaves de pub aquí. También necesitamos agregar esta pieza de código al método de configuración. Y vamos a crear una prueba llamada debería crear clave extendida. Cuando se le da una semilla mnemotécnica y una clave maestra derivada de ella. Cuando llamamos al método create desde el servicio extendido de claves de pub. Entonces esperamos que la llave de pub extendida creada sea igual a la esperada llave de pub extendida. Bien, entonces, ¿cómo vamos a crear estas variables en gris? pasaremos usando la cláusula where así. Se puede preguntar, ¿de dónde sacé estos valores? conseguí en el sitio web de ES Coleman io slash pip treonina. Este sitio web es muy útil para generar muchos tipos de claves y direcciones extendidas. Voy a copiar y pegar esta semilla mnemotécnica el campo BIP 39 en el sitio web para demostrar cómo funciona. Inmediatamente después de pegar la semilla mnemotécnica, la herramienta calculó la clave maestra de semilla raíz y las claves extendidas para mostrar el AT BIP derivado para las teclas extendidas, haga clic en esta pestaña. Vemos que la esperada clave pub y la prueba es igual a este valor en la página web. Al aplicar la función CKD a esta clave pública extendida con diferentes números ya que los índices obtendrán posteriormente claves públicas extendidas cuyas claves públicas extraídas serán utilizadas para generar recibiendo direcciones usando el mismo sitio web que creé para más casos de prueba. pegaré aquí y ajustaré el formato. Los dos últimos casos de prueba generarán claves de pub extendidas que se utilizarán para generar direcciones de cambio. Puedes copiarlos de los recursos de este video o hacer tus propios casos de prueba usando el sitio web de Ian Coleman. Usando la cláusula where, se ejecutará la misma prueba para cada parametrización que creamos. Vamos a hacer la prueba. La prueba falló como se esperaba. Ahora implementemos el método. Primero. Crearemos un mapa aquí que no abordará tipos a prefijos de claves de pub extendidos. Ambos tipos de dirección se asignarán al mismo prefijo de segmento neto principal. Al hacerlo, facilitamos la ampliación de esta funcionalidad si necesitamos agregar más tipos abordados más adelante. Ahora en el método create devolverá una nueva clave de pub extendida. Al pasar estos parámetros se pasará el retorno del método CKD desde la clave maestra, que tomará una ruta de derivación. False ya que no es una clave privada extendida y el prefijo del tipo de dirección. Después serializaremos el resultado. Y el segundo argumento extendido de la clave pub será el tipo de dirección y la forma de cadena. Por último, no olvidemos agregar aquí la anotación de servicio. Ahora, volvamos a ejecutar la prueba extendida de servicio de clave de pub. Genial, todos han pasado. Ahora ejecutemos nuestras pruebas de servicio de creación de billetera. Pero primero, hagamos algunos cambios a esta prueba. Debemos agregar el proveedor de seguridad, que es necesario para funcionen las funciones de criptografía Bitcoin Java. También tenemos que establecer los argumentos correctos para el servicio. Construyamos las configuraciones de direcciones y el servicio extendido de llaves de pub. Ahora vamos a ejecutarlo. Genial, las pruebas han pasado. Eso significa que nuestra billetera fue creada con una lista de claves públicas extendidas de tamaño dos. Uy, el índice de cambio aquí es uno. No va a afectar esta prueba ya que solo estamos afirmando que la billetera tendrá que extender las llaves del pub. Pero cambiémoslo a uno por el bien de la corrección. 18. 16 Creación de nuestra primera parte 8 skillshare 2: En este video, crearemos un vestido para cada llave de pub extendida que hace Wallet. Para ello, cada llave de pub extendida se pasará al método de vestidos generados, que creará ahora. Este método establecerá una lista de direcciones para el registro de clave de pub extendido. Vamos a crear este centro. Esta lista de direcciones será creada por un nuevo servicio generador secuencial de direcciones que creará. Utilizará un método de generación que tomará la clave de pub extendida y el tipo de clave de pub extendida. El servicio generador secuencial de direcciones tendrá este nombre porque generará un vestidos con un índice de derivación de direcciones creciente. Inyectemos el generador secuencial de direcciones en esta clase y creémoslo. Ahora, vamos a crear su método generate que devolverá una lista de direcciones. Vamos a crear el registro de dirección. Este registro tendrá un campo de dirección y un campo de índice. Ajustemos el método set addresses desde la tecla pub extendida. Tomará una lista de direcciones y establecerá el campo extendido de direcciones clave de pub. Vamos a crear una prueba para la clase de generador secuencial de direcciones. Por ahora, su método devolverá null. La clase de prueba extenderá la clase de especificación. Vamos a crear una prueba llamada debe generar 20 direcciones, usaremos el generador secuencial de direcciones en el bloque eólico. Entonces vamos a agregarlo como campo a esta clase. Cuando se llama al método generate con estos parámetros, es decir, una clave pública extendida en el tipo de segmento. Entonces esperamos que el regreso que lista de vestidos tenga una talla de 20. Puede copiar la clave pública extendida de esta prueba de los recursos de esta lección. Instanciemos el generador secuencial de direcciones en el método de configuración y ejecutemos la prueba. Falló como se esperaba. Ahora vamos a implementar el servicio declarará una llave de pub extendida. Entonces dentro de un bloque try catch se serializará y se serializará el parámetro clave recibido. El método serializado ANS transforma la clave de pub extendida en el objeto de clave de pub extendida de Bitcoin Java luego envolverá IOException en una excepción de tiempo de ejecución en el bloque catch. Ahora usaremos el método range desde la clase de flujo de pulmones hasta bucle de cero a una variable de número inicial de direcciones generadas que se establecerá más adelante. Inyectaremos esta variable en esta clase. En el constructor se establecerá una anotación calificador para esta variable, que tomará el mismo nombre de variable que un parámetro, cambiará su tipo a sugerencia, mapeará sobre cada índice y llamará el método generate address. Entonces, para cada índice, llamaremos al método generate address, pasando como parámetros el retorno del método Get de fábrica del generador de direcciones, la clave pub extendida y el índice. Por último, convertiremos el resultado en una lista. Vamos a crear el método generate addressed. Tomará un generador de direcciones y clave de pub extendida y un índice. El generador de direcciones se pasará de una fábrica de generadores de direcciones, que inyectará en esta clase y creará ahora. Cambiemos el parámetro type a address type. Ahora crearemos el método Get de fábrica del generador de direcciones . Devolverá una interfaz de generador de direcciones que creará ahora de nuevo al método de generar dirección desde el generador secuencial de direcciones. Primero derivaremos una clave secundaria extendida de la clave pub extendida usando el método CKD. Este método aplicará la función de derivación de claves secundarias que aprendimos hace dos videos. Tomará un índice que definirá el índice de derivación del niño. Ahora devolverá un nuevo registro de dirección. Tomará el resultado del método generate del generador de direcciones. Este método tomará la clave secundaria extendida y derivará una dirección de ella. El segundo parámetro de dirección será el índice. Ahora agregaremos el método generate a la interfaz del generador de direcciones. Ahora implementaremos el método get desde la fábrica de generadores de direcciones. Devolverá el resultado del GetMethod desde un mapa generador de direcciones. Esta variable será un campo en esta clase y será inicializada en este constructor de clase. Será un mapa de cadenas como claves y generadores de direcciones como valores. En el constructor pasará un servicio generador de direcciones de segmento, que creará. Después asignaremos cada tipo de dirección al generador de direcciones de segmento. En el mapa generador de direcciones. El generador de direcciones de segmento implementará la interfaz del generador de direcciones. Vamos a crear el método de interfaz requerido. Antes de implementarlo, vamos a crear su prueba. Extenderá la clase de especificación. Instanciará el generador de direcciones de segmento aquí. En el método de configuración agregaremos el proveedor de seguridad al igual que nuestras otras pruebas que lo necesiten. Entonces crearemos eso debería generar prueba de dirección de segmento. En el bloque dado se creará una clave de pub extendida utilizando la clase de clave de pub extendida en el método serializado. El método serializado tomará una cadena de clave pub extendida, que pasará en el bloque where. Luego crearemos un cuidado de niños extendido llamando al método CKD en la variable de clave de pub extendida. A este método pasará un parámetro index el cual pasará por el bloque web. Cuando se llama al método de generación de generador de direcciones de segmento con la clave secundaria extendida. Entonces esperamos que la dirección de devolución sea igual a la dirección esperada. Ahora, usemos el bloque where para inicializar las variables en gris usaremos los datos de prueba que han tomado del sitio web de E y Coleman para ello. Puede copiar estos parámetros de los recursos de esta lección. Vamos a hacer la prueba. Ha fracasado como se esperaba. En el siguiente video, conoceremos más sobre sig qué direcciones. Después en el video posterior al siguiente, implementaremos el generador de direcciones de segmento y el generador de direcciones secuenciales y haremos que sus pruebas pasen. 19. Comprender las direcciones de Segwit y la introducción a los entornos de la red de Bitcoin: En esta presentación, conoceremos más sobre las direcciones de segmento de Bitcoin, que será el tipo de dirección predeterminado que proporcionará nuestra billetera. Entonces, ¿qué es un segue de Bitcoin, qué dirección? Las direcciones de segmento también se conocen como direcciones nativas segue atrás 32 direcciones, direcciones segmento versión cero o P2 WP k-th direcciones, donde P2 WP k h significa pagar para presenciar hash de clave pública. Cada uno de estos términos se utiliza para referirse a lo mismo. Fue el tipo de dirección de Bitcoin más actualizado hasta noviembre de 2021. Después de noviembre de 2021, cuando se activó la actualización de raíz principal en la red Bitcoin, un tipo más nuevo de dirección de Bitcoin llamada dirección de raíz principal, puso a disposición un tipo más nuevo de dirección de Bitcoin llamada dirección de raíz principal, también conocida como dirección segue versión uno. Por ahora, centrémonos en la dirección del segmento, que la mayoría de las direcciones segmentadas de soporte de billetera moderna estuvo disponible en 2017 en la red Bitcoin después de la actualización de testigos segregados. Esta actualización permitió opcionalmente transacciones más pequeñas ya que la parte de estas transacciones más nuevas llamadas testigo se envía por separado y no está incluida en la cadena de bloques. Las reglas para generar direcciones de segmento se describen en VIP un séptimo tres y también se implementan en métodos de la biblioteca Bitcoin Java. Las direcciones de segmento permiten a los remitentes de Bitcoin pagar las tarifas más baratas por transacciones comunes. La razón de ello es porque las transacciones que envían bitcoins a direcciones de segmento son efectivas más pequeñas en comparación con las transacciones que envían a otro tipo de direcciones. Pero aprenderemos más detalles sobre las transacciones de Bitcoin en futuros videos. Debido a que las direcciones de segmento están bien respaldadas por mayoría de las billeteras modernas y porque nos permiten enviar transacciones más baratas, las estableceremos como el tipo de dirección predeterminada de nuestra billetera. Ahora, recapitulemos una diapositiva de la presentación anterior sobre las claves extendidas. En ese video aprendimos que podíamos obtener una clave pública a partir de una clave privada extendida o una clave pública extendida. Entonces, al hacer hash y codificar la clave pública, podríamos obtener una dirección. Ahora, veamos más detalles sobre este proceso de hash y codificación. Comenzando con una clave pública obtenida como se explicó anteriormente, aplicando las funciones hash criptográficas SHA-256 y 160 de la derecha a la clave pública, obtenemos un hash de clave pública con un tamaño de 20 bytes. El SHA-256, combinado con el 160 de la derecha , se denomina algoritmo hash 160. Finalmente, el hash de clave pública, combinado con un prefijo y una versión numérica, genera una dirección de segmento a través de la codificación Beck 32. La codificación Back 32 es reversible por el proceso llamado decodificación Beck 32. Al construir transacciones, debemos decodificar 32 direcciones a hashes de clave pública antes de incluirlas en las salidas de las transacciones. Es por eso que este tipo de dirección también se llama pay to witness public key hash revisitará este tema con mayor detalle al hablar transacciones para direcciones de segmento. Cuando Beck 32 codifica hashes de clave pública, la versión se establece en cero cuando el prefijo se establece en BC unnamed net. Hablando de la red principal, veamos rápidamente los entornos de red de Bitcoin. Cada uno de estos entornos es una red separada con diferentes blockchains y propósitos, pero reglas similares. El Bitcoin may net es como se le llama la red principal de Bitcoin. Es donde tienen valor los bitcoins. El blockchain es inmutable y la dificultad minera es la más alta. El entorno de red de prueba es similar a la red principal pero tiene una dificultad minera menor y donde los bitcoins no tienen valor, se utiliza para realizar pruebas en un entorno donde los nodos interactúan mientras mantener una cadena de bloques compartida. Test net ha tenido diferentes versiones desde que se creó con diferentes blockchains. Por último, el entorno de prueba reg es una red individual que puede ser ejecutada por cualquier usuario de nodo Bitcoin con una cadena de bloques no compartida con otros. Los bloques pueden ser generados instantáneamente, sin esfuerzo y libremente por el usuario. Se utiliza para realizar pruebas más rápidas y automatizadas en un ambiente controlado. Las direcciones en cada red tienen diferentes prefijos y son válidas solo en sus entornos. Para las direcciones de segmento, estas C es el prefijo utilizado para los vestidos rojos en la red principal. Tb se utiliza para direcciones en la red de prueba. Y BCRP es el prefijo usado para los vestidos rojos en la prueba reg. Como se dijo antes, la versión cero se utiliza para las direcciones de segmento. La versión uno se utiliza para las direcciones de raíz principal. 20. 18 Creación de nuestra primera cartera parte 9 skillshare 2: En este video, realizaremos todas las pruebas que hemos creado paths para hacerlo primero implementaremos el método generador de direcciones de segmento. Para generar una dirección de segmento se convertirá una clave extendida en una clave pública. Cambiemos este nombre de parámetro a clave extendida. Entonces la clave pública se convertirá a una dirección de segmento utilizando este método ya que su parámetro pasará un prefijo. Pasemos esta constante por ahora, que hará que la dirección sea válida en el entorno principal de Bitcoin neto. También agreguemos la anotación de servicio a esta clase. Ahora, ejecutemos la prueba del generador de direcciones de segmento. Ha fallado porque tenemos que elevar la versión Bitcoin Java a 0.4, 0.0, que contiene el método CKD correcto para esta operación funcione. Vamos a hacerlo. Haga clic en Cargar cambios de Maven. Volvamos a ejecutar la prueba. Genial, todas las pruebas han pasado. Ahora ajustemos la prueba del generador secuencial de direcciones. Tenemos dos nuevos parámetros constructores que tenemos que pasar al servicio. Primero, instanciemos la fábrica del generador de direcciones. Al pasar un nuevo seg se dirigiría al generador. Entonces pasaremos 20 es el número inicial de direcciones generadas. Ahora volvamos a ejecutar esta prueba. Bien, olvidamos agregar el proveedor de seguridad en el método de configuración. Vamos a arreglarlo. Ejecutarlo de nuevo. Bien, La prueba ha pasado. A algunos servicios les falta la anotación de servicio. Vamos a arreglar eso. Bien, ahora agreguemos un nuevo Bean, que será el número inicial de direcciones generadas para cada clave extendida, lo establecerá arbitrariamente en 20. Ahora vamos a ejecutar nuestra aplicación para ver cómo está funcionando. Recibimos un error en la consola indicando que nuestra aplicación le falta el proveedor de seguridad. Vamos a agregarlo al método principal en la clase de aplicación BYOD W. Volvamos a ejecutar nuestra aplicación. Bien, el error no ocurrió, pero al campo de dirección de recepción todavía le falta una dirección. Cambiemos esto. Primero. Realicemos todas nuestras pruebas para verificar qué otras pruebas necesitan ser arregladas. Las pruebas del servicio de creación de billetera están rotas. Vamos a arreglarlos. Primero, tenemos que incluir un objeto generador secuencial de direcciones válido como su tercer parámetro. Vamos a instanciarlo pasando 20 como primer parámetro y una fábrica de generadores de direcciones como el segundo. Entonces instanciaremos la fábrica igual que la prueba anterior. Ahora se asegurará de que el servicio create wallet esté creando una billetera con dos llaves de pub extendidas, cada una con 20 direcciones. Afirma que el primer campo extendido de direcciones clave de pub tiene un tamaño de 20. Vamos a crear un getter para este campo. Se hará valer lo mismo para la segunda llave de pub extendida. Ahora hagamos esta prueba. Genial, ya pasó. Ahora hagamos pasar la prueba de crear billetera. Recuerda que esperamos que la dirección de recepción TextField contenga una dirección después de crear una billetera. Entonces vayamos al controlador de pestañas de recepción. Se agregará un método llamado initialize, que se ejecutará después de que la aplicación inicialice este controlador. Entonces inyectaremos la cartera actual en esta clase. En la clase de billetera actual se incluirá un nuevo campo de propiedad de cadena simple llamado dirección de recepción, que se inicializará aquí mismo, creará setters y getters para ello. Ahora, vamos a la pestaña Recibir. Fxml agregará un Fx ID al TextField. Esta identificación ética se llamará dirección de recepción, y también la agregaremos al controlador de pestañas de recepción. Ahora, en el método inicializado vinculará la propiedad actual de dirección receptora de billetera a un oyente que tomará estos tres parámetros en una función Lambda. En el cuerpo Lambda establecerá el campo de dirección de recepción al nuevo valor, que será una dirección. Ahora en la actualización el servicio de billetera actual establecerá la dirección de recepción de billetera actual a la primera dirección de la primera billetera extendida clave pub. Ahora, cuando la dirección de recepción se cambie de esta manera, activará este oyente que hemos configurado aquí en el controlador de pestaña Recibir. Y ojalá agregue la dirección al campo de dirección receptora. Ahora, hagamos estas pruebas para ver si funcionan. Grupos. Ha fallado. Averiguemos por qué. Bien, el error ocurrió porque este método debe ser inicializado, no inicializado. Vamos a arreglarlo y ejecutar la aplicación. Genial. El monedero hizo lo que esperábamos y cumplió el campo de dirección de recepción después de haber creado una billetera. Ahora bien, si le presentamos esta dirección a alguien, puede enviarle bitcoins. Ahora, vamos a ejecutar todas las pruebas de aplicación. Genial, todos han pasado. 21. 19 Creación de nuestra primera parte de la billetera 10 skillshare 2: En este video, haremos un rápido refactor en el generador de direcciones de segmento. En lugar de codificar duro el prefijo del segmento de red principal como parámetro para la dirección del segmento a partir del método de clave pública comprimida creará un servicio que nos permitirá crear direcciones para la red de prueba y los entornos de prueba reg. Llamaremos a esta dirección de servicio prefijo de fábrica. Tendrá un método get donde pasaremos un tipo de dirección y devolverá un prefijo de dirección. Este valor devuelto se utilizará como parámetro para la dirección del segmento a partir del método de clave pública comprimida. Ahora inyectaremos este servicio en esta clase y lo crearemos. Ahora crearemos el método It's GET. Para implementar este método se necesitará un mapa auxiliar, que mapeará los tipos de direcciones a otro mapa, mapeando los tres entornos a sus prefijos de dirección correspondientes. Vamos a construirlo y quedará claro a lo que me refiero. Ahora, cambiemos este nombre de parámetro a tipo de dirección. En el getMethod devolverá un prefijo de dirección usando el tipo de dirección como primera clave. Y una variable llamada entorno Bitcoin como la segunda clave del mapa que acabamos de crear. La variable de entorno Bitcoin se definirá más adelante en nuestro archivo de propiedades de la aplicación, y la inyectaremos en esta clase. Ahora. En el constructor, agregaremos una anotación de valor antes la variable para inyectar su valor desde el archivo de propiedades. Ahora, vamos a escribir correctamente el campo de mapa de tipo de dirección. Ahora agreguemos la configuración del entorno Bitcoin al archivo de propiedades de punto de la aplicación. Lo pondremos a prueba reg. Ahora arreglemos algunos archivos de prueba para manejar los cambios que hemos realizado hasta ahora. Comenzando con la prueba del generador de direcciones de segmento, eliminará esta parte e instanciará el generador de direcciones de segmento en el método de configuración, pasando en la fábrica de prefijos de dirección como su parámetro. Ahora instanciaremos la fábrica de prefijos de dirección, pasando como parámetro la constante neta principal. Ahora vamos a ejecutar esta prueba. Genial, sigue funcionando. Ahora arreglemos la prueba del servicio de creación de billetera. Haremos lo mismo que en la última prueba. Simplemente inyecte la fábrica de prefijos de dirección en el generador de direcciones de segmento. Vamos a hacer la prueba. Genial, Ha pasado. Ahora arreglemos la prueba del generador secuencial de direcciones. Haremos lo mismo que antes. Ahora, hagamos la prueba. Genial, ya pasaron dos. Ahora vamos a ejecutar todas nuestras pruebas. Algunas pruebas fallaron porque a la fábrica de prefijos de dirección le falta una anotación. Vamos a arreglarlo. Vuelva a ejecutar las pruebas. Genial. Todas las pruebas han pasado. Ahora hagamos este pequeño refactor de agregar importaciones estáticas para estas constantes. Ahora, vamos a ejecutar la aplicación para ver qué hemos logrado hasta ahora. Recuerda que ahora esperamos que nuestra billetera genere direcciones compatibles con reg test ya que nuestra propiedad de entorno Bitcoin está configurada para reg test. Bien, como era de esperar, nuestra billetera generó direcciones comenzando con BCR t, ya que es el prefijo de direcciones de segmento en el entorno de prueba reg. Ahora vamos a cambiar el entorno Bitcoin propiedad dos red principal y ejecutar la aplicación de nuevo. Ahora tenemos direcciones que comienzan con BC, que es el prefijo de dirección de segmento para la red principal. Por último, cambiemos la propiedad del entorno Bitcoin para probar net y probar lo mismo. Bien, ahora podemos generar direcciones comenzando por TB, que es el prefijo para las direcciones compatibles con la red de prueba. Genial, ahora tenemos una manera fácil de cambiar el entorno de red compatible con nuestro monedero. 22. 20 nodo de preparación para recibir bitcoins skillshare 2: Ahora contamos con una billetera Bitcoin capaz de generar direcciones compatibles con diferentes entornos de red Bitcoin que son reg, test, test net y main net. Ya es posible usar estas direcciones para recibir Bitcoins. Para ello, solo necesitas mostrárselos a otros propietarios de bitcoin, que pueden usar sus billeteras para enviarte Bitcoins, o muy probablemente a Satoshi, que son fracciones de Bitcoin. Pero por ahora, nuestra billetera está habilitada para detectar estos pagos. Entonces no pasará nada en nuestra interfaz de usuario de billeteras después una transacción a una de nuestras direcciones. A partir de ahora, pretendemos cambiar eso. Comenzaremos a construir una función que nos permitirá escuchar las transacciones que llegan a nuestro nodo central de Bitcoin. Luego filtraremos las transacciones con salidas que coincidan con nuestras direcciones actuales de billetera. Finalmente, modificaremos nuestra billetera para mostrar información sobre la cantidad de Bitcoin que tiene nuestra billetera. Ahora asegurémonos de que nuestro nodo Bitcoin esté correctamente configurado y preparado para enviar y recibir información de transacción a nuestra billetera. Para ello, abre el archivo bitcoin.com. La ubicación de este archivo dependerá del sistema operativo que estés usando. Como estoy usando Windows ten, mi archivo bitcoin.com se encuentra en la ruta de acceso en la pantalla. Abre el archivo y asegúrate de que se vea así. Revisemos el significado de cada una de estas configuraciones. El primer parámetro, reg test se establece en uno para hacer que nuestro nodo se ejecute en los entornos de prueba reg. Ya que usaremos el entorno de prueba reg para ayudarnos a desarrollar nuestra aplicación. El segundo parámetro, los datos allí se establece en la carpeta que desea que el nodo registre la información de blockchain y billetera. Yo puse el mío a los dos puntos backslash los datos de Bitcoin, pero puedes elegir cualquier ruta que prefieras. El parámetro del servidor se establece en uno para permitir que nuestro nodo reciba llamadas API desde nuestra aplicación. Los parámetros de usuario RPC y contraseña de RPC se pueden ajustar a lo que quieras. Por ahora, elegiré BYUI W para ambos. Pero al usar nuestra aplicación de verdad, es muy recomendable elegir valores más seguros para estos parámetros. El índice TX se establece en uno. Esto es necesario para que nuestro nodo pueda recuperar cualquier información de transacción de la cadena de bloques. El parámetro de tarifa de reserva se puede establecer en 0.00 001. Este valor se utilizará para tarifas de transacción que no pudieron ser calculadas adecuadamente por el nodo. Por último, estableceremos la propiedad z MQ pub Ratti x a este valor. Esta propiedad establece la dirección TCP donde la información de transacción que va la información de transacción que llega al nodo. Nuestra aplicación, escucharemos la misma dirección TCP y capturaremos nuevas transacciones enviadas a una de nuestras direcciones Bitcoin de esta manera. Ahora, ejecutemos nuestro nodo Bitcoin con estas configuraciones usando el terminal, vaya a la carpeta donde está instalada tu aplicación Bitcoin. Esto depende de dónde lo instalaste y qué SO estés usando. Como estoy usando Windows diez, ya abrí mi terminal y fui a esta carpeta en la pantalla. Ahora ejecuta el nodo Bitcoin escribiendo dot slash Bitcoin D y presionando Enter. Ahora su nodo central de Bitcoin se está ejecutando con las configuraciones. Dijimos anteriormente, ya estamos listos para las próximas clases. 23. 21 cliente de nodo parte 1 skillshare 2: En este video, crearemos un cliente HTTP que hará algunas llamadas a nuestro nodo central de Bitcoin. Este cliente será necesario más adelante cuando lo usemos para enviar y recibir transacciones. Primero, vamos a importar una dependencia en el archivo POM. Esta dependencia es la web de inicio de Spring Boot, que es necesaria para la implementación del cliente HTTP, excluirá una dependencia transitiva de esta biblioteca agregando una etiqueta de exclusión. La dependencia excluida será el arrancador de Spring Boot Tomcat. Lo haremos para evitar iniciar un servidor web en nuestra aplicación. Ahora, da clic en el botón Cargar cambios de Maven. Ahora hagamos una clase de configuración para el cliente de nodo. Cree una clase llamada Node client configuration dentro del paquete api dot config en una anotación de configuración para él. Ahora, crearemos algunas propiedades privadas en esta clase, todas precedidas por una anotación de valor. El primero tendremos esta anotación de valor. Y se llamará nodo RPC URI. El siguiente tendrá esta anotación de valor. Y será el nodo RPC username tendrá otra propiedad con la siguiente anotación de valor con el nombre igual nodo contraseña RPC. Todas estas propiedades se inyectarán a partir de valores que se agregarán posteriormente en el archivo de propiedades de punto de la aplicación también se creará una viga con la clase de plantilla de resto. Tomará un descanso Template Builder como parámetro. Usaremos este constructor para devolver el objeto de plantilla de detención con un URI raíz igual a la propiedad URI de RPC de nota. Tendrá una autenticación básica con la nota nombre de usuario RPC y las propiedades de contraseña de nota RPC. Entonces llamaremos a Build y regresaremos. Ahora vamos a asignar las propiedades que se van a inyectar en esta clase. Vamos al archivo de propiedades del punto de la aplicación. Vamos a asignar a la propiedad nodo punto RPC punto URI la siguiente dirección. Este URI con puerto 18443 es el URI predeterminado para la API RPC de Bitcoin Core Node para el entorno de prueba reg. Como propiedad node dot RPC dot username, tienes que elegir el mismo valor que has elegido para la configuración de usuario RPC en tu archivo bitcoin.com como la propiedad node dot RPC dot password, elige el mismo valor que has establecido para la configuración de contraseña de RPC en tu bitcoin.com. Ahora dentro del paquete api dot services, crea el paquete node, incitado, crea el paquete cliente. Ahora vamos a crear la clase cliente nodo dentro de ella. Vamos a agregarle la anotación de servicio. Ahora, vamos a inyectar el resto de frijol plantilla en esta clase. Añadiremos el siguiente método para realizar solicitudes a la API de Bitcoin RPC. En cuanto a sus parámetros, tomará un método de cadena, una referencia de tipo parametrizada de tipo node client response, que creará a continuación una URL de cadena y cero o más objetos. Ahora vamos a crear la respuesta flexible del nodo dentro del nodo de punto de dominios de paquete. Volver al método cliente nodo instanciará un nuevo objeto de solicitud de cliente de nodo. Tomará los argumentos del método y los parámetros en su constructor. Vamos a crear esta nueva clase dentro de los dominios, ese paquete de nodos. Vamos a crear su constructor. Ahora, envolveremos la solicitud dentro de un objeto de entidad HTTP. Luego devolveremos el resultado de esta llamada al método, que finalmente hará una solicitud posterior al nodo Bitcoin Core, ajustará la clase de respuesta del cliente del nodo, transformará en una registrar y agregarle una propiedad de resultado hará un ajuste similar a la solicitud del cliente del nodo, lo transformará en un registro y le agregará estos campos. Nos hemos olvidado de poner una T aquí mismo. Ahora, veremos cómo hacer una llamada importante a la API de Bitcoin Core Node. Ir a este sitio web en la pantalla. Es una referencia a la llamada Create Wallet Bitcoin core RPC. Vemos en la última línea que esta llamada toma una clave de método con el valor crear billetera en su cuerpo. Cada llamada a la API de Bitcoin tiene este formato con la clave de método que contiene el nombre del método. Las llamadas a la API de Bitcoin también tienen una clave params que contiene varios tipos de datos. En este caso, su valor es una matriz con un solo elemento. El nombre de la billetera, la llamada create wallet crea una billetera dentro del Bitcoin Core y la carga. requieren muchas llamadas a API que usaremos más tarde. Pero nuestro nodo central de Bitcoin tiene una billetera cargada. Volver al nodo cliente. Ahora podemos entender por qué el método make request construye un objeto request que toma un argumento de cadena llamado method y un argumento de tipo variable llamado params. Ahora vamos a crear una clase llamada node create wallet client. Vamos a agregarle una anotación de Servicio. Inyectará el cliente del nodo en él. Ahora vamos a crear un método llamado create, que tomará un parámetro de cadena. Ahora para hacer una llamada al método create wallet de la API Bitcoin Core. Los llamaremos make request method del cliente del nodo así, siguiendo la referencia del sitio web de Bitcoin Core. Ahora vamos a probar este método para eso. Ejecutemos nuestro Bitcoin Core Node en la terminal. En lugar de usar nuestra forma tradicional de hacer las cosas con TDD, probaremos este método de manera diferente. Volver al nodo crear cartera cliente creará un método precedido por una anotación post build. La anotación Post constructo es útil para ejecutar código cuando se inicia una aplicación de resorte. También es útil para pruebas rápidas y aplicaciones Spring, casi como crear un método estático principal en una clase Java, pero con todos los beneficios de los beans administrados por la aplicación. Dentro de este método se llamará al método create pasando cualquier nombre de billetera. Ejecutemos la aplicación. Bien, Al ver los registros de Bitcoin Core Node en el terminal, vemos que nuestro nodo creó y cargó una billetera con el nombre que hemos dicho en la llamada al método. Con eso, sabemos que nuestro método está funcionando y podemos eliminar este método post build. Ahora, volvamos al sitio web de Bitcoin Core y busquemos el método DIR de cartera de listas. Este método no toma parámetros y devuelve todas las billeteras de nodo creadas hasta ahora. Devuelve una estructura JSON con un campo de billeteras. Este campo contiene una matriz de objetos, cada uno de los cuales representa una cartera existente con un campo de nombre. Vamos a crear un cliente para este método. Lo llamaremos lista de nodos mientras sea cliente. Nuevamente, vamos a inyectar el cliente de nodo en esta clase. Después crearemos el método list all, que devolverá una lista de nombres de billetera. Dentro de este método los llamaremos make request method from the node client passing list wallet DIR como el nombre del método. Una nueva referencia de tipo parametrizada y una URL vacía. No pasaremos ningún parámetro adicional. El objeto devuelto será un registro de monederos de nodo, que creará ahora, lo crearemos dentro del paquete de nodos punto de dominios. Este registro tendrá sólo un campo. Será una lista de billeteras de nodo. Su nombre serán billeteras. Vamos a crear el registro de monedero de nodo en el mismo paquete. Su único campo será un nombre de cadena. Recuerda que estamos modelando estos objetos a partir de esta referencia del sitio web de Bitcoin Core. Pero el campo de billeteras en el registro de billeteras del nodo coincide con el nombre de este campo en la respuesta JSON de la llamada API. Lo mismo ocurre con el campo de nombre del registro del monedero del nodo. El campo de billeteras de la respuesta tendrá una lista de objetos con el campo de nombre. Cada uno de estos objetos se almacenará como registros NerdWallet en la aplicación de vuelta a la lista de nodos mientras es cliente. De la lista, todo método devolverá una lista de nombres de billetera. Para ello, obtendremos las billeteras de las billeteras de nodo. Luego llamaremos a stream, luego mapearemos pasando una referencia al campo del nombre de la billetera del nodo. Después convertiremos el resultado a una lista y lo devolveremos. Ahora, vamos a probar el método list all usando un método anotado con Post build imprimirá cada elemento devuelto por la lista de todos los métodos de llamada. Vemos por esta línea en la consola que la aplicación registra el nombre del monedero de nodo que hemos creado. Genial. Ahora implementaremos otro cliente para llamar al método Node API llamado list wallets. La diferencia entre este método y la cartera de lista DIR es que las billeteras de lista devolverán solo las billeteras cargadas actualmente por el nodo. También devuelve una lista de nombres de cartera sin envolverlos en objetos. Ahora vamos a crear el método list loaded. Devolverá una lista de nombres de billetera. Para ello, sólo tenemos que devolver esta llamada al método. Ahora vamos a probarlo de la misma manera que hemos probado la lista. Voy a llamar. Vemos desde la consola, pero nuestra aplicación registra dos veces el nombre de la billetera que hemos creado. El primero se debió a la llamada al método list all, y el segundo se debió a la llamada al método list loaded. Ahora bien, para ver la diferencia entre las dos llamadas a métodos, hagamos lo siguiente. Termine la aplicación Bitcoin Core Node presionando Control más C en el terminal. Ahora inicia de nuevo el Bitcoin Core Note. Ahora hagamos la misma prueba. Pero primero, sumar estas líneas antes de que el método llame a diferenciar entre cada método. Desde la consola, vemos que solo la lista all method call devolvió la billetera creada. Esto demuestra que después de que iniciemos la aplicación Bitcoin Core Node, tenemos que cargar la billetera que usaremos, para que podamos realizar otras llamadas API que necesiten cargar una billetera de nodo. Pero veremos cómo funciona eso en la práctica en los próximos videos. 24. 22 cliente de nodo parte 2 skillshare 2: En este video, seguiremos implementando más métodos que nos permitirán interactuar con nuestro nodo Bitcoin desde nuestra aplicación. El primero es un método que cargará una billetera de nodo. Cuando ejecutas tu nodo, necesitas cargar una billetera para poder llamar a muchos otros métodos de nodo. Así que vamos a crear el cliente de cartera de carga de nodo. Como siempre, en una anotación de Servicio al mismo. Ahora, inyectaremos el cliente del nodo en él. Después crearemos el método load, que tomará como parámetro el nombre de las billeteras. Entonces simplemente los llamaremos make request method desde el cliente del nodo así. Ahora, probemos este método usando una construcción post. Primero, eliminemos este método post constructo que hemos creado antes. Ahora llamaremos al método load pasando el nombre de la billetera que creamos. Antes de ejecutarlo, ejecutemos nuestro nodo Bitcoin en la terminal. Bien, desde los registros de la terminal, vemos que nuestro nodo cargó correctamente nuestra billetera. Ahora crearemos un servicio útil para cargar una cartera de nodo si ya existe y no está cargada. Si ya existe una cartera con ese nombre y ya está cargada por el nodo entonces el método no hará nada y volveremos. Por último, si no existe una billetera con ese nombre, el método la creará y el nodo se cargará automáticamente ya que carga una billetera después de su creación. Entonces en el paquete services dot node, vamos a crear una carga de nodo de nombre de clase o crear un servicio de billetera. Inyectemos a los siguientes clientes en él. El nodo crea cliente de billetera, el cliente de billetera de carga nodo y la lista de nodos mientras su cliente. Ahora vamos a crear un método llamado load o crear wallet. Tomará un nombre como parámetro. En su interior se llamará a la lista todo método de la lista de nodos billeteras cliente almacenará el resultado en una variable llamada todas las billeteras. Después llamaremos al método list loaded desde el mismo cliente. Y almacenaremos el resultado en la variable monederos cargados. Ahora, agregaremos una declaración if verificando la siguiente condición. Si esta condición se evalúa como true, significa que la billetera con ese nombre ya existe y es cargada por el nodo. Si ese es el caso, no necesitamos hacer nada y podemos regresar. Ahora, agregaremos la siguiente declaración if. Si esta declaración devuelve true, significa que ya existe una billetera con ese nombre, pero no es cargada por el nodo. Si ese es el caso, llamaremos al método load desde el nodo load wallet client pasando el nombre de la billetera y devolveremos. Finalmente, si la ejecución del código evalúa como falsas las declaraciones IF anteriores, significa que no existe una billetera con ese nombre. En ese caso, simplemente creamos la billetera, llamando al método create desde el nodo create wallet client y pasando el nombre de wallets. Bien, El método está terminado. Lo usaremos en los próximos videos. Ahora vamos a crear otro cliente útil. Se llamará Node get new address client. Como su nombre indica, se utilizará para generar una nueva dirección a partir de nuestro monedero de nodo cargado. Así que vamos a inyectar el cliente del nodo en él. Ahora, vamos a crear un método llamado get new address. Devolverá la dirección en una cadena. Y tomará como parámetro el nombre de la cartera. Después volveremos a hacer la llamada al método request desde el cliente del nodo con estos parámetros. Observe que hemos establecido el parámetro URL la cadena Wallet barra el nombre de la billetera. Es así como le decimos a nuestro nodo que queremos una dirección de esta cartera específica. Probemos este método. Para eso, crearemos el siguiente método anotado Post constructo llamará al método get new address pasando el nombre de una billetera que hemos cargado antes como parámetro. Si llamamos a este método sin cargar esta billetera First, no funcionará y el nodo devolverá un error. Almacenaremos el resultado de la llamada al método en la variable address y lo imprimiremos. Vamos a probarlo. El registro de la consola, muestran que generó e imprimió una dirección de prueba reg de segmento de Bitcoin. Genial. Toma nota de tu dirección generada. Lo usaremos para probar el método que va a implementar a continuación. Ahora, vamos a crear un método que se utilizará para la mente algunos bloques que producen Bitcoins a una dirección. Este método solo funciona en el entorno de prueba reg, y nos será útil en algunas pruebas que necesitan un número inicial de monedas para jugar. Vamos a crear una clase llamada no degenerate para dirigirse al cliente. Como de costumbre, inyectaremos el cliente del nodo en él. Después crearemos un método llamado generate to address. Tomará como parámetros, un nombre de billetera, un número de bloques y una dirección. Después los llamaremos make request method desde el cliente nodo con los siguientes parámetros. Nuevamente, pasaremos la cadena Wallet barra la variable name. Después pasaremos el parámetro blocks, que indica el número de bloques que se quiere generar. Por último, pasaremos la variable address, que es la dirección que recibirá los Bitcoins generados. Ahora, vamos a probar este método. Primero. Eliminemos el método anotado de construcción post anterior . Ahora, haremos que este método post constructo llamará al método generate to address, pasando el nombre de una billetera cargada. Nuevamente, si pasas el nombre de una billetera que no existe o no está cargada, el método funcionará. Crearemos 1,000 bloques y pasaremos la dirección previamente generada. Vamos a ejecutarlo. Si inspeccionamos nuestros registros de nodos, vemos que muestra algunas líneas que indican que nuestro método llamado funcionó. El último cliente que creará para este video se llamará Node get balanced client. Se utilizará para verificar el saldo de nuestras billeteras. Inyectemos el cliente del nodo en él. Después crearemos el método get, que devolverá el número de bitcoins que tiene nuestra billetera. Tomará como argumento el nombre de la billetera. Después devolveremos esta llamada al método. Al igual que los métodos anteriores. Este método enviará a la Wallet barra el nombre de la billetera como parámetro URL para definir el retorno del saldo de esta billetera específica. Probemos este método usando una construcción post. Llamará al método get pasando el nombre de una billetera previamente cargada. Nuevamente, este método no va a funcionar. Si el monedero pasado no es cargado por el nodo, entonces almacenaremos el resultado de la llamada en una variable e imprimirlo . Vamos a probarlo. Genial. A partir de los registros, vemos que ahora tenemos miles de Bitcoins. Por supuesto, estos bitcoins solo son válidos en nuestro entorno de prueba reg. En los próximos videos, los usaremos para probar. 25. 23 cliente de nodo parte 3 skillshare 2: En este video, construiremos un cliente que nos permitirá enviar Bitcoin desde nuestra billetera de nodo a cualquier otro vestido rojo que queramos. Luego usaremos todos los clientes que hemos construido hasta ahora para crear una prueba para recibir bitcoins a una dirección de nuestra billetera de aplicaciones. Así que después de eliminar cualquier método de construcción post anterior de lecciones anteriores, vamos a crear una clase llamada nodos enviados a cliente de dirección. Ahora vamos a inyectar el cliente del nodo en él. Luego crearemos un método llamado send to address como parámetros o nombre de billetera y dirección y una cantidad. Después los llamaremos make request method desde el nodo cliente pasando los siguientes parámetros. Nuevamente, pasaremos Wallet recortando la variable de nombre de billetera. Será la billetera desde donde se enviarán los bitcoins. También tomará una dirección a donde se enviarán los bitcoins y una cantidad, que es la cantidad que se transfiere en Bitcoins. Probemos este método. Primero, asegúrate de que tu nodo se esté ejecutando. En mi caso, voy a tener que iniciarlo. Ahora, asegurémonos de que nuestra billetera de nodo esté financiada con Bitcoins para que podamos enviar bitcoins desde ella llamará al método get balanced para verificar eso. Pero esta vez lo llamaremos desde la terminal. Cada método API que podamos llamar desde nuestra aplicación se puede llamar desde el terminal usando la aplicación Bitcoin CLI. Abre otra ventana de terminal, ve a la misma carpeta donde está instalado tu nodo. Luego escribe el siguiente comando para cargar una cartera previamente creada y presiona Enter. En mi caso, después de cargar billetera, tengo que escribir testing wallet name, que es el nombre de la billetera creé entre comillas dobles. Bien, ahora que nuestra cartera está cargada, podemos ingresar otros comandos que lo requieran. Entonces ingresemos este comando para verificar nuestro saldo de billetera. Bueno, está equilibrado, es cero. Parece que cada vez que reiniciamos la nota y el entorno de prueba reg, nuestros fondos desaparecen. No hay problema. Financiaremos nuestra cartera de nodos. Ahora usando la interfaz de línea de comandos. Para ello, primero, obtenemos una nueva dirección de nuestro nodo mientras así es. Entonces llamamos al comando generate to address para generar 1,000 bloques y destino el bloque recompensa a la dirección que acabamos de generar. Ahora, llamemos nuevamente al comando Get balanced. Genial. Vemos que nuestra cartera ahora contiene miles de Bitcoins. Otra vez. Ahora de vuelta al nodo enviar a domicilio cliente. Hagamos un método post build para probar el método send to address. Llamará al método de enviar a dirección, pasando el nombre de la billetera cargada. El segundo parámetro puede ser cualquier dirección de prueba reg. Usaremos la CLI de Bitcoin para generar una nueva dirección. Después lo pasaremos como segundo parámetro al método send to address. Entonces elegiremos uno como la cantidad. Vamos a ejecutarlo. Bien, si llamamos al método Get balanced de la CLI de Bitcoin, veremos que nuestro equilibrado apenas cambió. Hay una pequeña diferencia entre el saldo actual y el saldo anterior. Esta diferencia se debe a la tarifa de transacción ya que transferimos un Bitcoin a una dirección desde el mismo monedero de nodo, si llamamos al método get received by address desde la CLI. Pasando la dirección, hemos enviado un Bitcoin al número cero como segundo parámetro, lo que indica que queremos el saldo, incluidas las transacciones no confirmadas, obtenemos el valor uno, que es la cantidad que lo transferimos a esta dirección. Bien, por ahora hemos terminado nuestro CLI jugando. Eliminemos el método de construcción Post. Ahora dentro del paquete BYOD w dot gooey creará la prueba receive Bitcoin. Esta prueba necesitará muchas cosas en común con la prueba de crear billetera. Entonces haremos que extienda una clase abstracta que crearemos llamada prueba GUI. Esta clase tendrá todos los métodos comunes a cualquier prueba GUI que necesitemos. Así que vamos a crearlo. En la prueba create wallet cortará todas las propiedades y métodos excepto el último y los transferirá a la clase de prueba GUI. Luego le agregaremos la anotación de prueba Spring Boot y extenderá la clase de especificación de la aplicación. Eliminaremos la misma anotación de la prueba create wallet y haremos que extienda la clase de prueba GUI. Eliminemos todas las importaciones no utilizadas. Ahora hará que todas las propiedades privadas en la prueba GUI estén protegidas e incluirá esta llamada de proveedor de agregar punto de seguridad en su método de inicio. Por último, haremos que esta clase sea abstracta. Ahora, probemos la prueba de crear billetera para ver si todo sigue funcionando como antes en el error ocurrido. Mi intuición dice que es un error de idea IntelliJ. Para resolverlo, llamémoslos método de ciclo de vida limpio maven. Reconstruyamos también el proyecto y ejecutemos todas las pruebas de aplicación. Todas las pruebas pasaron. Entonces solo fue un error IDE. Ahora, sigamos construyendo nuestra prueba de recepción de Bitcoin inyectará los siguientes beans en ella. El nodo envía al cliente de dirección, el nodo carga o crea el servicio de monedero. El nodo se balancea, cliente. Y el nodo consigue nuevo cliente de dirección. *****. Parece que olvidamos agregar la palabra cliente y el nodo obtener nueva dirección. Vamos a cambiarle el nombre. Ahora, vamos a crear un método de configuración que se ejecutará antes de que esta clase sea test. En su interior llamará al método load o create wallet desde el nodo load o creará servicio wallet ya que su parámetro pasará la cadena, probará wallet y lo almacenará en la constante. Entonces llamaremos al método create balance si es necesario, que creará a continuación. Este método, primero comprobaremos el saldo de la cartera de prueba usando el nodo get balanced client. Si el saldo es inferior a 100 Bitcoin, entonces obtendremos una nueva dirección de la billetera de prueba. Usando el nodo generar para direccionar al cliente, que nos hemos olvidado de inyectar en esta clase, y lo haremos ahora. Generaremos 1,000 bloques, financiando así nuestra billetera. Y haremos que este método sea privado. Con este método ejecutándose antes de las pruebas, garantizamos que siempre tendremos Bitcoins que podremos usar en nuestras pruebas. Ahora, vamos a crear una prueba llamada debería recibir Bitcoin. Es cuando el bloque será similar al bloque de viento en la prueba de crear billetera, llamaremos a los siguientes métodos para crear una nueva billetera. Haremos clic en la pestaña Recibir. Después buscaremos el valor en la entrada de la dirección de recepción, que en este punto contendrá la primera dirección de nuestra billetera. Y lo almacenaremos en la variable dirección. Ahora, llamaremos al método send to address desde el nodo enviado al cliente de dirección. Como sus parámetros pasarán el nombre del monedero de prueba, la dirección que hemos generado con nuestra cartera de aplicaciones, y la cantidad uno. Después de recibir Bitcoins, esperamos que nuestra cartera de aplicaciones detecte la transacción, pero este proceso no será inmediato. Tomará algunos segundos para que eso suceda. Por esta razón, usaremos un método llamado wait-for de test fx. Como sus parámetros pasarán diez, que será el valor de tiempo de espera para el peso. El tiempo de espera en este contexto es el tiempo máximo que esperará la aplicación antes de lanzar una excepción de tiempo de espera. El segundo parámetro indica la unidad de tiempo del parámetro anterior. Entonces elegiremos segundos. El último parámetro será un método de devolución de llamada. En su interior buscará un componente GUI con un ID de direcciones. Table, consultará tiene un TableView y almacenará su resultado en una variable del mismo tipo. Después devolvemos la comparación entre el tamaño del artículo TableView y uno. Esta tabla TableView con ID de direcciones será un componente que almacenará una tabla que contiene filas, cada una con una dirección financiada de nuestra billetera. El método callback se ejecutará en un bucle y solo se detendrá si la comparación devuelve true o si se logra el tiempo de espera. En resumen, este peso para la llamada al método hará lo siguiente. Se comprobará si hay una tabla con una fila rellenada en la pantalla. Esto sucederá cuando nuestra billetera detecte que una de sus direcciones recibió una transacción y llenó una fila de tabla con esa información. Esperará 10 s a que eso suceda o menos. Si la tabla se llena con una fila antes, entonces copiaremos la línea de búsqueda de vista de tabla y la pegaremos aquí. Entonces block comprobará de nuevo si el tamaño del elemento TableView es igual a uno. Almacenemos este valor de tiempo de espera en una constante. Ahora, hagamos la prueba. Como se esperaba. La prueba falló porque no encontró la tabla de direcciones. En el siguiente video, comenzaremos a implementar esta función en nuestra billetera. 26. 24 Recepción de bitcoin parte 1 skillshare 2: En este video, crearemos una tabla con información sobre nuestras direcciones. Esa tabla contendrá cada dirección financiada, su monto en Bitcoin y el número mínimo de confirmaciones que tienen las transacciones a esas direcciones. La idea es llenar esa tabla justo después nuestras billeteras detecten transacciones enviadas a nuestras direcciones. Entonces en la ventana principal punto FXML, si hacemos clic en la pestaña Scene Builder, veremos que está mostrando un mensaje para descargar Java FX, aunque lo hayamos descargado antes. Esto sucede porque esta función IDE no maneja bien los componentes externos, como el controlador de pestañas Recibir. Así que para poder utilizar el Scene Builder se creará un nuevo archivo FXML llamado playground. En este archivo, pegaremos todo el contenido de la ventana principal punto FXML. Pero en lugar de usar componentes externos como el controlador de pestañas Recibir, los incorporará en el archivo. Así que dentro del paquete resources dot FXML, cree el archivo playground dot FXML. Eliminar todo su contenido. Después copia todo el contenido de la ventana principal punto FXML y pégalo ahí. Ahora sustituiremos el contenido de la etiqueta Recibir tab controller por el contenido de la pestaña Recibir punto FXML. Y modificaremos la etiqueta raíz FX con la etiqueta tag. Y vamos a eliminar su atributo type. Importemos la etiqueta de insertos. Ahora, cuando hacemos clic en el Scene Builder, podemos usarlo normalmente. Ahora, agreguemos un nuevo panel de pestañas al componente VBox. Ahora, eliminemos una de las pestañas creadas. Vamos a cambiar el nombre de las dos direcciones de la pestaña restante. Vamos a darle una ficha FX id de direcciones. Ahora, dentro de la pestaña Contenido, agregaremos un componente de vista de tabla. Desafortunadamente, por razones de errores, Scene Builder no nos permite agregar una vista de tabla a una pestaña. No hay problema. Vamos a agregarlo usando el editor de texto. También agreguemos aquí una idea de Fx de la tabla de direcciones. Volvamos al Scene Builder. Empezó a funcionar de nuevo. Ahora tenemos una tabla vacía dentro de la pestaña de direcciones. Ahora agregaremos tres columnas a la tabla. Cambiaremos el nombre de la primera columna dos direcciones, la segunda para equilibrar, y la tercera dos confirmaciones. Después haremos clic en la tabla y cambiaremos esta configuración a redimensionamiento restringido. Ahora, cada columna tiene el mismo tamaño y ocupan toda el área de la mesa. Ahora vamos a hacer clic en cada columna de la tabla y deseleccionar. Son casillas de verificación editables y clasificables. Ahora, para cada columna de tabla establecerá su ancho máximo en 100. Esto es solo un truco necesario para que podamos ajustar su tamaño. Ahora, ajustemos su tamaño usando el mouse así. La columna de direcciones debe ser más grande ya que las direcciones ocuparán un espacio mayor, las columnas de saldo y confirmación pueden tener el mismo tamaño. Volver al editor de texto. Cambiemos el atributo pref height del panel de tabulación a 355. Volviendo al Scene Builder, podemos ver que se ve mejor. Cambiemos también el mensaje de marcador de posición, que muestra cuando la tabla está vacía. Para ello, solo necesitamos agregar una etiqueta de etiqueta vacía dentro de esta etiqueta de marcador de posición. Ahora que nuestro componente de mesa está listo en el patio de recreo, vamos a crear un FXML para ello. Vamos a nombrarla tabla de direcciones. Eliminemos todo su código estándar. Y vamos a copiar todo el contenido entre la etiqueta TableView y pegarlo ahí. Ahora, en lugar de usar la etiqueta de vista de tabla, usemos la etiqueta raíz FX hace referencia a las plantas de vista de tabla y al atributo type. Importemos las etiquetas restantes. Y agreguemos aquí este atributo XML y S. Ahora de vuelta a la zona de juegos FXML. la pestaña de direcciones le falta un FX ID. Vamos a agregarle. Esta idea ya se utilizó en el componente VBox por error. Así que vamos a quitarlo de ahí. Ahora, vamos a copiar estas cuatro líneas y pegarlas en la ventana principal. Ahora, agreguemos las etiquetas de cierre y las etiquetas que copiamos. Ahora eliminaremos la etiqueta de vista de tabla y agregaremos una etiqueta de contenido en su lugar. En su interior agregará una etiqueta de controlador de tabla de direcciones. Ahora vamos a crear este controlador. Vamos a agregarle una anotación de componente. Debe extender la clase de vista de tabla con la clase address como su parámetro type. Ahora de vuelta a la ventana principal. Vamos a importar el controlador creado recientemente. En el controlador de la tabla de direcciones, vamos a crear un constructor. Tomará un parámetro FXML con una anotación de valor. La anotación de valor hará referencia a la tabla de direcciones FXML. El segundo parámetro constructor será un objeto de contexto de aplicación. En el cuerpo del constructor se creará un nuevo objeto cargador FXML, inicializándolo con estos parámetros. Entonces configuraremos su controlador FXML a esto. Y fijaremos su ruta a esto. Entonces llamaremos a cargar en él. Y agregaremos una declaración de lanzamientos al constructor. Tenemos que hacer una cosa más para que funcione. Dentro de esta sentencia if en la interfaz gráfica de usuario iniciado oyente añadir el siguiente código. Esto es necesario para que Java FX construya correctamente la etiqueta del controlador de direcciones. Ahora, ejecutemos nuestra aplicación para ver cómo funciona. Genial, bien, la mesa de vestidos se ve bien. En los próximos videos, haremos que funcione para nuestras billeteras. 27. 25 Recepción de bitcoin parte 2 skillshare: En este video, haremos que nuestras billeteras comiencen a interactuar con nuestros nodos Bitcoin para que podamos recibir información sobre transacciones enviadas a nuestras direcciones. Recuerda que cuando creamos una billetera, generamos las primeras 20 direcciones para ello. Pero nuestro nodo Bitcoin aún no sabe sobre son direcciones generadas. Son nodo Bitcoin debe conocer nuestras direcciones para enviar activamente información sobre sus transacciones a nuestra aplicación. Por lo tanto, necesitamos importar nuestras direcciones de billetera a nuestro nodo. Para ello, crearemos un nuevo cliente de nodo que se encargará de ello. Así que dentro del paquete de cliente nodo punto se creará una clase llamada nodo multi import address client. Al igual que otros clientes, tendrá una anotación de servicio e inyectaremos el servicio al cliente del nodo en él. Antes de crear su método, revisemos la documentación del sitio web de Bitcoin Core para que su API utilice el multimétodo de importación desde la API del nodo Bitcoin. Vemos aquí que toma como parámetro una matriz de objetos. Cada objeto puede tener muchas claves diferentes, pero solo usaremos tres de ellas. La clave pub script, que puede tomar como valor y objeto con una dirección que el nodo importará una marca de tiempo, que es la fecha en que se generó la dirección. Este parámetro es importante para determinar hasta qué punto en el pasado el nodo buscará transacciones con esa dirección en la cadena de bloques, también establecerá el parámetro watch only en true ya que nuestro nodo solo usará nuestras direcciones para monitorear transacciones en la cadena de bloques, pero no podrá firmar transacciones con esas direcciones. Solo nuestra cartera de aplicaciones podrá firmar transacciones salientes, pero ese es un tema para futuros videos. De vuelta al IDE, vamos a crear un método llamado direcciones de importación. Tomará como parámetros un nombre de billetera, una lista de direcciones y una fecha de creación de billetera. Ahora construiremos un objeto params que modelará el multiparámetro de importación que vimos en la documentación de Bitcoin Core. Este objeto será una lista de un nuevo objeto que crearemos llamado nodo multi reimportado dress params. Vamos a crearlo ahora. Será un registro y lo crearemos en el paquete de nodos puntos de dominios. Contará con un nuevo nodo multi reimportado, le volverá a proyectar script pub key objeto va a crear. También tendrá un campo de marca de tiempo largo y un campo de solo reloj booleano. Vamos a crear esta clase como un registro. Tendrá sólo un campo de dirección. Volver al nodo cliente de dirección de importación múltiple. Dado que el método import addresses recibe una lista de direcciones, debemos usar el siguiente código para convertirlo en una lista de nodos multi reimportados vestido por ohmios. Entonces usaremos el método make request del cliente del nodo así. Ahora, probemos este código usando un método de construcción posterior. Importaremos direcciones a la billetera del nodo con el nombre de la billetera de prueba de nombre. Y usaremos la fecha actual como fecha de creación del monedero. Como las direcciones. Utilizará estas tres direcciones de prueba reg, que podrás encontrar en esta clase como recursos. Antes de ejecutar este código, ejecutemos nuestro Bitcoin Core Node y carguemos la billetera con el mismo nombre que usaremos. Para cargarlo se utilizará la CLI de Bitcoin, tal como hicimos en videos anteriores. Bien, Al mirar los registros del nodo Bitcoin, parece que funcionó. La última línea del registro muestra que se completó el reanálisis. El reanálisis ocurre por defecto después de importar direcciones al nodo. La búsqueda de reanálisis de transacciones en la cadena de bloques para las direcciones recientemente importadas. En este proceso, el nodo busca transacciones y bloques creados hasta 2 h antes de la fecha que hemos pasado como parámetro timestamp. Eliminemos el método de construcción Post. Ahora dentro del paquete de oyentes de puntos pegajosos, Vamos a crear una clase llamada cartera creada oyente importante. Tendrá una anotación de componente, e implementará la clase de escucha de aplicaciones con un parámetro de evento de billetera creado. Vamos a implementar su método. Al igual que el oyente de billetera creado, esta clase es método se llamará después de la creación de una billetera. Inyectemos la carga del nodo o creemos el servicio de billetera en él. Ahora, en el método de evento no aplicación se llamará al método load o create wallet desde el servicio inyectado pasando el nombre de la billetera de eventos como parámetro. También inyectemos el cliente de direcciones de importación múltiple de nodo en él. Hagamos que ambos servicios inyectados sean definitivos. Ahora llamaremos al método import addresses desde el último servicio inyectado. Pero primero, vamos a crear una variable para el monedero del evento y utilizarla en este método. Ahora en la llamada de direcciones de importación, Pasemos el nombre del monedero. El método wallet get addresses, que creará la billetera creada en la propiedad, que también crearemos en el registro de billetera. Vamos a crear la propiedad CreateDat date, crearemos usando la función IDE de cambio de firma. Usemos un valor predeterminado de nueva fecha. Al hacerlo, el IDE agregará automáticamente este tercer parámetro en cada instancia de una billetera que encuentre en el proyecto. Vamos a hacer clic en Refactorizar e importar la clase de fecha. Si vamos al servicio create wallet, vemos que agregó una nueva fecha como tercer parámetro en la instanciación de wallet. Esto hará que el monedero tenga la fecha actual como fecha de creación. El controlador de diálogo create wallet utilizará la billetera creada en la llamada al método de evento público. Esto activará la llamada al método de evento en la aplicación. Ahora vamos a crear el método get addresses en el registro de la billetera. Devolverá una lista de direcciones tomando las direcciones de sus llaves de pub extendidas, así. Al llamar al método FlatMap en el flujo de claves de pub extendidas y devolver el flujo de direcciones de clave de pub extendido en esta llamada obtendrá un flujo de todos los Objetos de Dirección de la billetera. Luego llamaremos al método map para convertir el flujo de objetos de dirección en un flujo de cadenas de direcciones. Finalmente, llamaremos al método de dos listas en el resultado y devolveremos una lista de todas las direcciones de billetera en formato de cadena. Bien, ahora después de crear nuestra billetera, esperamos que nuestras cargas de aplicaciones fueran crea una billetera con el mismo nombre en nuestro nodo. Después de eso, nuestra aplicación importará todas las direcciones generadas a nuestro nodo. Ejecutemos nuestra aplicación para probarla. Vamos a crear una nueva cartera. Yo hice clic en el botón Bien, pero parece que no había pasado nada. Comprobemos los registros del nodo. Bien, después de algún tiempo, dice que el reanálisis se completó y el monedero terminó su creación. En el siguiente video, haremos que este proceso sea asincrónico ejecutando las llamadas al nodo en otro hilo. Al hacerlo, el pegajoso no se quedará atascado y la creación de la billetera será más suave. Cia. 28. 26 Recepción de bitcoin parte 3 skillshare 2: En el último video, hicimos que nuestro nodo Bitcoin creara y cargara nuestra cartera de aplicaciones y direcciones de importancia. Pero este proceso estaba tardando algunos segundos y estaba bloqueando la interfaz gráfica de usuario. En este video, lo arreglaremos haciendo que la comunicación con el nodo se ejecute en otro hilo de forma asíncrona dentro del paquete BYU OWL. Vamos a crear un nuevo paquete llamado Config. Dentro de este paquete, vamos a crear una clase llamada config asincrónica. Esta clase contendrá todas las configuraciones relacionadas con la ejecución de código asincrónico en el proyecto. Vamos a agregarle una anotación de configuración. Y una anotación asíncrona habilitada para. Esta anotación es importante para habilitar entidades asíncronas en el proyecto. Ahora, vamos a crear un método anotado con la anotación Bean. Devolverá un EjecutorService. Vamos a llamarlo servicio ejecutor predeterminado. Devolverá un nuevo ejecutor de un solo hilo de la clase ejecutores. Este bean nos proporcionará un hilo cada vez que queramos ejecutar código en él. Será un solo hilo, que significa que si dos o más secciones de código están tratando de ejecutarse en este hilo simultáneamente, una sección tendremos que esperar a que la otra termine de ejecutarse. Elegimos usar un solo hilo porque facilita el control de los procesos en nuestra aplicación y nos permite evitar condiciones de carrera con mayor facilidad. Ahora, hagamos un poco de refactorización de código dentro del paquete gooey dot services. Vamos a crear una clase llamada servicio de monedero de importación y agregarle la anotación de servicio. Vamos a crear un método llamado monedero de importación. Transferirá el código del oyente de importación de billetera creado al servicio de billetera de importación. Inyectemos también los servicios requeridos en esta clase. Y agreguemos la billetera como parámetro al método de la billetera de importación. En el oyente de importación de billetera creado. Eliminemos todo este código. Inyectemos el servicio de monedero de importación en él. Ahora en el método de evento que no es de aplicación, llamemos al método import wallet desde el servicio inyectado pasando la billetera de eventos como parámetro. El método import wallet contiene el código que queremos ejecutar de forma asincrónica. Para hacerlo asincrónico, solo tenemos que anotar este método con la anotación asincrónica, pasando el nombre del bean del servicio ejecutor que hemos creado. También debemos devolver un valor de este método, que nos permitirá administrar esta llamada asincrónica desde el método color. El valor devuelto será un futuro. Un tipo de parámetro void devolverá un nuevo objeto de resultado asíncrono que pasa null a su constructor. Ahora, probemos la creación de una billetera. Pero primero, ejecutemos nuestro nodo Bitcoin. Si no está ya funcionando. Vemos que nuestra billetera se creó de inmediato, pero cuando revisamos los registros de los nodos, sigue cargando e importando las direcciones de la billetera. Genial. El nodo ha terminado el reanálisis. Por lo que nuestros procesos de carga e importación de billeteras son asíncronos. Ahora hagamos algunas afinaciones finas. Vamos al oyente de importación de billetera creado. En el método de evento no aplicación se registrará la devolución del método de monedero de importación y lo almacenará en la variable de resultado. Haremos de esta variable un campo privado de esta clase. Ahora, agregaremos la siguiente declaración if. Antes de llamar a la cartera de importación. Si la variable result no es nula, entonces llamaremos al método cancel en ella, pasando true como argumento. Esto es necesario porque si intentamos crear otro monedero cuando uno no haya terminado de importar primero, tendremos que cancelar el proceso de importación de la primera billetera creada. Hagamos otra afinación fina en la clase de aplicación GUI anulará el método stop. En su interior, se agregará el siguiente código. Este código asegurará que el hilo creado por nuestro ExecutorService predeterminado se cierre después cerrar nuestra aplicación. Ahora, hay otro problema con nuestra aplicación. Cuando creamos una billetera sin nuestro nodo Bitcoin funcionando, las llamadas para crear o cargar una billetera y direcciones de importancia fallarán. Veamos cómo funciona eso en la práctica cerrando nuestro nodo Bitcoin y ejecutando nuestra aplicación. Después de crear una billetera, parece que nuestra aplicación se está ejecutando normalmente, pero eso es porque las excepciones y otros hilos no están siendo reportados. Nuestra billetera no podría haberse comunicado con nuestro nodo mientras nuestro nodo estaba apagado. Cuando intentó hacer eso, arrojó una excepción hilo arrojó una excepción y un hilo terminó de funcionar. Arreglemos esto. Lo que queremos que haga nuestra aplicación cuando crea una billetera es intentar comunicarnos indefinidamente con nuestra nota. Si por alguna razón no pudo hacerlo después del primer intento, hágalo, usaremos una anotación Spring Boot llamada retrial. Esta anotación hace que el método anotado se ejecute de nuevo, si arroja una excepción. Para usarlo, debemos agregar las siguientes dependencias a nuestro archivo POM. El primero es el reintento de resorte, el segundo son los aspectos de primavera. Ahora en el método import wallet, agreguemos la anotación de retrial también le pasará algunos parámetros. La primera será la expresión de excepción, que se establecerá como al inicio de sesión puerto wallet service dot debería reintentar abrir y cerrar paréntesis. Esto hará que la aplicación llamada un método should retry antes cada reintento y solo reintente si esta llamada al método devuelve true. También agregaremos el parámetro max intentos, configurándolo en la constante de número entero de valor máximo. Esta configuración hará que este método se vuelva a intentar indefinidamente. Por último, agreguemos el parámetro backoff, configurándolo a la anotación de retroceso, pasando el parámetro delay de 1,000. Esto hará que la aplicación esperara 1,000 milisegundos o 1 s antes de ejecutar el método en cada intento. Ahora vamos a crear este método debería reintentar. Su tipo de retorno será un Booleano. El método devolverá la negación del resultado de que se interrumpa la llamada al método del hilo actual. Esta llamada devolverá true si el hilo actual no es interrumpido o falso en caso contrario. Por lo tanto, si la aplicación se cierra o si se crea otra billetera entre cada reintento, este hilo se interrumpirá y el método de monedero de importación ya no se volverá a intentar. Una cosa más para que funcione la anotación de reprueba, debemos agregar la anotación de reintento habilitada en la clase de configuración asíncrona. Vamos a hacerlo. Ahora. Ejecutemos nuestra aplicación con nuestro nodo cerrado y hagamos algunas pruebas. Vamos a crear una nueva cartera. Ahora, comencemos nuestro nodo. A partir de los registros del nodo, vemos que se cargó la billetera creada y se ha completado el reescaneo. Ahora. Ahora vamos a crear otra cartera. Vemos desde los registros del nodo que también se ha creado, cargado e importado con éxito . Genial. 29. 27 Recepción de bitcoin parte 4 skillshare 2: En este video, seguiremos integrando nuestra billetera con nuestro nodo. El siguiente paso en la integración es escuchar los mensajes que el nodo envía cuando recibe una transacción a una dirección importada. Para ello, crearemos una clase llamada node task, que tendrá un método que ejecutará en un bucle infinito en otro hilo después de que se inicie la aplicación. Este método escuchará continuamente las transacciones que son nodo recibe a cualquiera de nuestras aplicaciones direcciones cargadas actuales. Cuando encuentre uno, hará que nuestra aplicación lo maneje en consecuencia. Así que vamos a crear un nuevo paquete llamado node en el paquete BYOD W. En su interior se creará una clase llamada gooey started node listener. Vamos a agregarle una anotación de componente. Esta clase será un oyente desencadenado por el evento gooey started publicado cuando se inicia la aplicación. Por lo que implementará el listener de aplicaciones con ese evento como su parámetro de tipo. Implementemos su método. Vamos a agregar el nuevo servicio de tareas de nodo que creará como un campo privado en esta clase. Vamos a crear el nuevo servicio. Ahora, vamos a inyectarlo en el oyente de nodo iniciado GUI. En el método de evento que no es de aplicación se llamará al método de ejecución de tareas de nodo. Vamos a crear este método en la tarea del nodo. Agreguemos la anotación de servicio a esta clase. Ahora, agregaremos una dependencia que la tarea de nodo necesitará en el archivo POM. Será el héroe de la biblioteca MQ. Vamos a hacer clic en el botón Cargar cambios de Maven. Esta biblioteca gestiona la comunicación entre la aplicación y cero MQ. Zero MQ es un corredor de mensajes que recibe mensajes del nodo Bitcoin. Estos mensajes serán enviados a una URL local y recopilados por nuestra aplicación a través de cero MQ de regreso a la tarea del nodo. Agreguemos la anotación asíncrona al método run. Pasemos el servicio albacea de notas como su parámetro. Esto hará que este método se ejecute asincrónicamente en otro subproceso gestionado por el servicio ejecutor de nodo que vamos a crear en la clase de configuración asíncrona, vamos a crear el servicio ejecutor de nodo. Al igual que el servicio ejecutor predeterminado, será administrado por un nuevo ejecutor de un solo hilo. Ahora, vamos a inyectar el objeto socket desde cero MQ en esta clase. Este campo se llamará suscriptores ya que manejará una suscripción al broker de mensajes MQ cero. En el método run, vamos a establecer el tiempo de espera de recepción del suscriptor en 1,000. Esto agregará un retraso de un segundo cada vez nuestra aplicación consulta cero y Q para buscar mensajes. Llamemos a este método de suscripción de suscriptores, pasando los bytes de la varilla de cadena TX como parámetro. Esto hará que nuestra aplicación solo escuche mensajes relacionados con robar transacciones de Bitcoin que son envíos de nodo a cero. Mq también llamará al método de conexión de suscriptores, pasándole la variable z MQ URL a él. Inyectemos esta variable en esta clase. Añadiremos una anotación de valor a su argumento constructor, pasando esta cadena como parámetro. Por lo tanto, este valor de variable se inyectará en esta clase a través una propiedad de aplicación llamada z y q punto URL se establecerá ahora, el valor de esta variable tiene que coincidir con el mismo valor que hemos establecido en nuestro archivo bitcoin.com. Así que vamos a copiar el valor establecido para la configuración z MQ pub rock TX bitcoin.com y pegarlo aquí. Ahora, de vuelta al método de ejecución de tareas de nodo vamos a crear nuestro bucle sin parar. Vamos a crear un bucle while. Se ejecutará mientras no se interrumpa el hilo actual. Dentro del bucle, llamaremos a los suscriptores wreck el método STR y almacenaremos el resultado en la variable topic. El naufragio del método STR consulta cero MQ para cualquier mensaje y devuelve una cadena si encuentra uno. En nuestro caso, esa cadena contendrá el nombre del tema, que será igual a ra TX para las transacciones en bruto. Luego agregaremos un bucle if verificando la variable topic. Si su contenido es diferente a Ratti x, entonces llamaremos a continue making the loop run again from the beginning. Si no, entonces llamaremos al método abonados naufragio V y almacenaremos el contenido en la variable content. El naufragio del método es similar al VNTR rec, pero devuelve una matriz de bytes en lugar de una cadena. En este punto, esa matriz de bytes contendrá la transacción sin procesar o nodo enviado a cero MQ. Ahora, convertiremos la matriz de bytes en el objeto de transacción Bitcoin Java. Para ello, usaremos el siguiente código. Debemos agregar una sentencia lanza IOException a esta firma de método. En la GUI inició el nodo oyente. También necesitamos envolver la llamada de ejecución en un bloque try-catch como este. Volver al método run. Ahora usaremos un servicio de editores de eventos de aplicaciones para publicar un evento. Inyectemos este servicio en esta clase. Primero. Pasaremos un nuevo evento de transacción recibida al método publish event. A la transacción recibida instanciación del evento pasará esto y el objeto de transacción antes crear la nueva clase de evento, agreguemos una pieza faltante para que este método funcione. Vamos a crear una nueva clase llamada configuración de nodo. Vamos a moverlo a un nuevo paquete node dot config. Vamos a agregarle una anotación de configuración. En esta clase, agregaremos algunos beans para las tareas del nodo inyectado objeto Socket funcionen. El primer frijol será el contexto Z siendo. El segundo haz será el zócalo MQ cero. Se llamará suscriptor. Y tomará en su método el contexto Z creado anteriormente. Devolverá los contextos Z para crear llamada al método socket pasando la subconstante de tipo socket como su parámetro. Ahora de vuelta a la tarea nodo se creará el evento de transacción recibida, lo creará en el paquete de eventos de punto de nodo. Pasaremos la tarea de nodo al súper constructor e inyectaremos la transacción en un campo de transacción privado. Creemos también un método getter para la transacción. Ahora, vamos a crear un paquete de oyentes en el paquete node. En su interior. Vamos a crear un oyente de transacciones recibidas para este evento. Vamos a agregarle una anotación de componente. Este oyente se encargará de filtrar las transacciones de recepción identificando si tienen direcciones pertenecientes a una cartera actualmente cargada. Implementará un oyente de aplicación con el evento de transacción recibida como su parámetro de tipo. Implementemos su método. En este método, obtengamos transacción del evento y almacenemos en la variable de transacción. Ahora, lo primero que haremos es identificar las direcciones de salida de la Transacción Recibida. Para hacerlo se creará la variable addresses, que será una lista de cadenas. Después le asignaremos el resultado de la siguiente expresión. Mapeará las salidas de la transacción pasando un método de análisis de analizador de direcciones. Ahora, vamos a inyectar y crear el servicio de analizador de direcciones. Vamos a crearlo en el paquete node dot services. Vamos a agregarle la anotación de servicio. Ahora, vamos a crear el método parse. Devolverá una cadena y tomará una salida de transacción como su parámetro. Este método se encargará de extraer la dirección de una salida de transacción de vuelta al oyente de transacción recibida convertirá el resultado en una lista. Entonces para fines de prueba se imprimirán todas las direcciones analizada. Ahora vamos a implementar el método parse. Lo primero que haremos es obtener la clave pub del script de transacción y asignarla a esta variable. No te preocupes, te explicaremos qué es una clave de pub de guión y otros detalles de la transacción. En el siguiente video, devolveremos el resultado de la siguiente sentencia switch. Si el tipo de la clave pub script es igual a la constante P2 WP k, h, que es el tipo de nuestras direcciones actuales de billetera. Después devolveremos el script pub key P2, WP k h address method call. Pasando el prefijo de dirección Factory Get method call como parámetro que le pasa la constante Segway. La sentencia case predeterminada será una cadena vacía. Inyectemos la fábrica de prefijos de dirección en esta clase. Ahora, hagamos algunas pruebas. Mi nodo Bitcoin ya está funcionando. Asegúrate de que el tuyo también. Vamos a la clase de prueba de recibir Bitcoin y ejecutarla. La prueba falló porque aún no hemos modificado nuestra prueba GUI para considerar el controlador de tabla de direcciones. Recuerde que nuestro oyente iniciado GUI maneja el problema de usar esta condición if. Podríamos usar la misma condición si en nuestro fijo, pero hagámoslo de una manera más ordenada. Vayamos al evento iniciado GUI. Cambiemos el tipo de aplicación GUI a object. Simplemente publicaremos el evento gooey started en nuestra clase de prueba GUI, la misma manera que lo hicimos aquí en la clase de aplicación GUI. En la clase de prueba GUI, eliminemos todo este código. Ahora, copiemos esta línea de la aplicación GUI y péguela aquí. Eliminemos todas estas importaciones no utilizadas y este campo privado no utilizado. Ahora, volvamos a ejecutar la prueba de recibir Bitcoin. Nuestra prueba falló, pero vemos aquí en los registros de prueba que son aplicación impresa dos direcciones. Esto sucedió porque imprimimos las direcciones de la transacción que nuestra prueba realizó una de nuestras direcciones de billetera. Una de estas direcciones es la nuestra, la otra es una dirección de cambio del remitente. Genial. Vemos que lo que hemos hecho hasta ahora ha funcionado. Hagamos algunas refactorizaciones en la clase de prueba GUI. Eliminemos estas importaciones no utilizadas. En la clase de aplicación GUI. Incluyamos esta línea de código que hará que nuestro hilo de servicio ejecutor note deje ejecutarse después de cerrar nuestra aplicación. En el siguiente video, aprenderemos más sobre las transacciones de Bitcoin para prepararnos para lo que viene después. 30. Transacciones de Bitcoin entradas, salidas, guiones y el conjunto UTXO: En esta presentación, aprenderemos algunos conceptos sobre las transacciones de Bitcoin. Será útil para entender mejor la implementación de recibir Bitcoins en nuestra cartera de aplicaciones. Recapitulemos lo que hemos aprendido hasta ahora sobre las transacciones de Bitcoin y gradualmente agreguemos complejidad a nuestra comprensión de ellas. Entonces, una transacción de Bitcoin se usa comúnmente para transferir Bitcoins de persona a persona B. Una transacción de Bitcoin puede estar compuesta por muchas entradas y muchas salidas. Una entrada de transacción indica el propietario anterior de Bitcoin o el remitente de la transacción. Una salida de transacción indica el receptor de las monedas o el propietario de las monedas después se publique la transacción. En esta imagen, tenemos una transacción simple con una entrada y dos salidas. Dice que un Bitcoin fue transferido de John, quien firmó el insumo de esta transacción. La salida cero indica que 0.9 Bitcoins fueron enviados para casarse. Voy a poner uno indica que 0.099 Bitcoins fueron enviados de vuelta a John como el cambio. Los montos de Bitcoin no se pueden dividir en entradas. Ya que John quería enviar 0.9 Bitcoins para casarse, pero solo tenía un Bitcoin. Necesitaba crear una salida de cambio de nuevo a Sí Mismo. Pero su cantidad es de 0.099 Bitcoins, no 0.1 Bitcoins, como cabría esperar. La diferencia, que es 0.001 Bitcoins, es la tarifa de transacción necesaria para que la transacción se incluya en la cadena de bloques. Entonces a partir de esta imagen, tomamos tres lecciones. La suma de bitcoins en entradas no puede ser menor que la suma de Bitcoins y salidas. El monto de Bitcoin en entradas es fijo mientras que se puede elegir a voluntad y salidas dado que satisface la regla anterior. Por último, la tarifa de transacción es la diferencia entre la suma de los montos de Bitcoin en las entradas y la suma de los montos y salidas de Bitcoin. Incrementando la complejidad. También aprendimos sobre los campos que forman parte de una entrada de transacción y una salida de transacción. Y entrada siempre se refiere a una salida de una transacción anterior. Lo hace usando el ID de transacción anterior y el índice de salida de la transacción anterior. Sería redundante que la entrada tuviera un campo de cantidad. Estos dos campos son suficientes para identificar cualquier salida de transacción en la cadena de bloques. Uh, la entrada de transacción también debe contener una firma válida producida usando la misma clave privada utilizada para derivar la dirección de la salida a la que se refiere la entrada. Observe que una entrada de transacción no tiene un campo que indique que es cantidad de Bitcoin. Eso es porque su cantidad es automáticamente igual a la cantidad de salida a la que se refiere una salida de transacción tiene dos campos. Una es la dirección que se utiliza para recibir bitcoins. Y la dirección es una cadena codificada y por sí misma no revela al dueño de las monedas. Por eso consideramos a Bitcoin seudónimo. El otro campo es la cantidad que indica la cantidad de Bitcoin bloqueada por la dirección. Ahora, aumentemos la complejidad una vez más explicando qué contienen exactamente las entradas y salidas de las transacciones. La entrada de transacción tiene los siguientes campos. El ID de transacción anterior, que es una cadena hexadecimal única, se obtiene mediante hash de la transacción serializada anterior. El índice de salida de transacción anterior es un número entero. Dado que una transacción puede tener muchas salidas, una salida específica puede identificarse inequívocamente por su ID de transacción e índice de salida. El campo ScriptSIG o testigo. La firma de entrada se agrega al campo ScriptSig en transacciones que no sean Segway. En las transacciones Segway, la firma se agrega al campo testigo, que no cuenta al tamaño de la transacción. La salida de la transacción tiene los siguientes campos. La clave del pub script. clave de publicación de script contiene la dirección decodificada y el campo de cantidad que determina la cantidad de Bitcoin bloqueada por la dirección. Ahora, veamos cómo construir una transacción de Bitcoin a través de un ejemplo. Nuestro objetivo en este ejemplo es enviar 1.5 bitcoins a esta dirección. Antes de comenzar, tenemos una transacción confirmada, lo que significa que ya está almacenada en la cadena de bloques. Tiene una salida con dos bitcoins, que puedo gastar ya que tengo una clave privada que se utilizó para crear su dirección, y que se puede usar para firmar una entrada de transacción para ello en una nueva transacción. Así que vamos a construir una nueva transacción, le agregará una entrada. La entrada nos referiremos a nuestra transacción a través del campo ID de transacción anterior. El índice de salida de transacción anterior es cero, ya que es el índice de salida de nuestra salida. El campo ScriptSig está compuesto por una firma producida usando la misma clave privada utilizada para producir la dirección de nuestra salida. Y una clave pública, que es la misma clave pública derivada usando nuestra clave privada. La transacción tendrá dos salidas. El cero de salidas contendrá un campo de clave de pub de script compuesto, entre otras cosas, la clave pública hash de la dirección. Queremos enviar nuestros bitcoins a. Este hash es obtenido por Beck 32 decodificando la dirección. Atrás 32 es el algoritmo utilizado para codificar el hash de una clave pública, produciendo un segundo ¿qué dirección? Base 58 es otro algoritmo utilizado para hacer lo mismo para direcciones que no son de segmento. Ya que estamos enviando bitcoins a una dirección de segmento, debemos usar Beck 32. El campo de cantidad de esta salida será igual a 1.5, que es la cantidad de Bitcoin que queremos enviar, necesitará una segunda salida para el cambio. Su clave pub script contendrá una clave pública hash obtenida por la decodificación Beck 32 y la dirección que nos pertenece, que se deriva de una clave privada sobre la que tenemos control. cantidad será de 0.49 Bitcoins, que sumado a 1.5 de salida cero es igual a 1.99. Entonces tenemos una diferencia de 0.01 entre la suma de los montos de Bitcoin en entradas y salidas. Esa diferencia será la tarifa de transacción necesaria para la transacción sea incluida en la cadena de bloques por un menor. Hablamos de ScriptSiG y script pub key, pero aún no explicamos cuáles son esas cosas realmente. Bitcoin tiene un lenguaje de contrato inteligente llamado script. Un contrato inteligente es una forma elegante de referirse a un programa escrito en una transacción y ejecutado por la red Bitcoin. Los campos clave ScriptSIG y script pub están hechos con código de lenguaje script. Este lenguaje se interpreta combinando el scriptSIG de una entrada y la clave pub script de una salida y comprobando si el scriptSIG satisface las condiciones codificadas por la clave pub script. Puedes considerar este mecanismo como un mecanismo de llave y cerradura, donde el ScriptSig es la llave para desbloquear la clave script pub, que es la cerradura. Si un ScriptSIG es válido para desbloquear una clave de pub script, entonces puede gastar los fondos de salida bloqueados por él. Un ScriptSIG tiene este nombre porque generalmente contiene una firma que satisface una condición específica de clave de pub de script. De igual manera, la clave pub script tiene este nombre porque contenía una clave pública en las primeras transacciones de Bitcoin. Pero en teoría, cualquier código de script arbitrario se puede incluir en ambos campos. La restricción única para que un programa de script sea válido es que devuelve true al final de su ejecución. Hay muchos tipos de programas de script, también conocidos como tipos de script. Uno de ellos es el hash de pago a clave pública utilizado en transacciones simples no secuitur. Veamos cómo se ejecuta en este ejemplo, todos los scripts de Bitcoin se ejecutan de manera similar, ¿qué cambios entre ellos o el código que se está ejecutando? Entonces, comenzando con nuestra transacción confirmada de la diapositiva anterior, aquí, mostramos solo su salida cero con su contenido clave de pub script en la caja gris. En las transacciones hash de pago a clave pública, el campo script pub key se compone de opcodes y el hash de clave pública. Y opcode es una instrucción en lenguaje de escritura. Están identificados por las letras OP en sus inicios. Subir guión bajo igual, por ejemplo, compara dos elementos y devuelve true si son iguales. Cada script pub key y pay to public key hash scripts tiene esta secuencia de código que solo difiere en sus hashes de clave de pub. Ahora tenemos nuestra nueva transacción, que es la misma que la diapositiva anterior. En esta ocasión mostramos solo su aporte aquí. Es el contenido de ScriptSig está en la caja gris. En pago a scripts hash de clave pública. El ScriptSiG sólo tiene una firma seguida de una clave pública. Ahora veamos cómo se combinan y ejecutan ambos campos. Primero, el contenido ScriptSig de la entrada se concatena con el contenido de la clave pub script de la salida referida por la entrada en este orden. Luego, cada elemento del script combinado es empujado a una pila de ejecución de izquierda a derecha. Si el elemento es un opcode, puede actuar sobre otros elementos de la pila, procesándolos y agregando otros elementos a la pila. Entonces veamos cómo se ejecuta este script. La firma es el primer elemento de izquierda a derecha. Por lo tanto, primero se introduce en la pila. El siguiente elemento es la clave pública, y también se introduce en la pila. El siguiente elemento es el opcode arriba subrayado. Arriba, subrayado arriba codifica una instrucción para duplicar el último elemento agregado a la pila y agregar la copia a la pila. El siguiente elemento es el opcode op underscore hash 160. Elimina el último elemento agregado a la pila, aplica la función hash 160 y vuelve a agregar el resultado hash a la pila. Entonces terminamos con el hash de clave pública en la parte superior de la pila de ejecución. El siguiente elemento que se agregará a la pila es el hash de clave pública. A continuación, tenemos el guión bajo op igual verificar opcode. Este opcode elimina dos elementos de la parte superior de la pila de ejecución y los compara si son iguales a lo que el script continúa ejecutándose. Si no es así, su ejecución falla y la transacción se invalida. Este paso es importante porque valida que la clave pública del ScriptSIG es igual a la clave pública utilizada para generar la dirección de la salida de la que está gastando. El último elemento del script es el opcode sig de verificación de guión bajo op. Elimina dos elementos de la parte superior de la pila de ejecución y valida si el primer elemento es una firma válida para el segundo elemento para esta transacción específica, si es una firma válida, agrega un verdadero booleano a la pila. Si no es válido que un booleano, se agrega false a la pila. Finalmente, después de que se agregaran todos los elementos del script a la pila de ejecución, la entrada de transacción se consideraría válida si el último elemento agregado es true. De lo contrario, la entrada de transacción no es válida. Este proceso debe repetirse para cada entrada de transacción. Para que una transacción se considere válida, todos sus insumos deben ser válidos. Hay muchos tipos de guiones. El script pay to public key fue el primer script de Bitcoin creado, pero hoy en día está en desuso y rara vez se usa. Las primeras transacciones de Bitcoin contienen el tipo de script. En lugar de usar el hash de la clave pública, es script pub key, usa la clave pública directamente. El script hash de pago a clave pública se ejemplificó en la última diapositiva. Fue el tipo de script más utilizado desde el aumento de relevancia de las transacciones Segway en los últimos años. Hoy en día, sigue siendo de uso común, por lo que es bueno saberlo. El script hash de clave pública pay to witness es el tipo de script más utilizado actualmente en las transacciones de Bitcoin. La razón de esto es que es ventajoso usarlo ya que las transacciones con él son más pequeñas y por lo tanto tienen una tarifa de transacción más pequeña. Este tipo de script tiene una clave de publicación de script más pequeña y su contenido de ScriptSig se mueve al campo testigo, lo que no contribuye al tamaño de la transacción. Por estas razones, primero implementaremos este tipo de script en nuestras billeteras, el hash pay-to-script es otro script utilizado principalmente para transacciones multifirma. Las transacciones multifirma requieren más de una firma para gastar una salida. El hash del script pay to witness es la versión testigo del script hash pay-to-script. Su firma se traslada al campo de testigos. Por lo que tiene las mismas ventajas que tiene el script hash de clave pública pay to witness. El hash de clave pública de pago para presenciar envuelto en un script hash de pago a script también se conoce como segmento anidado o segmento de rap. También es de uso común y su función principal es hacer carteras antiguas que no son compatibles con segmentos nativos, compatibles con transacciones Segway. Aprenderemos más sobre el tipo de guión más adelante en el curso. Por último, otro tipo de script es el script root pay to tap. Es el tipo de script creado más recientemente, agregando más capacidades y privacidad a las transacciones de Bitcoin. Ahora, veamos un resumen de cómo construir entradas y salidas de transacciones desde el punto de vista de una billetera, comenzando con una semilla mnemotécnica y una frase de contraseña. A través de un algoritmo criptográfico, combinamos ambos y obtenemos una semilla raíz. Después a través de una serie de transformaciones se producen claves maestras y llaves extendidas. Obtenemos muchas claves privadas. Aquí te mostramos solo una de estas claves privadas. Las mismas transformaciones también pueden producir claves públicas. Una clave pública también se puede producir a partir de una clave privada específica, que mostramos aquí en nuestro ejemplo. A partir de una clave pública, obtenemos una dirección usando la función hash 160 y codificando el resultado a través de la codificación Beck 32 en el caso de direcciones de segmento o codificación base 58 en el caso de direcciones que no son de segmento. Para recibir Bitcoins, le muestras tu dirección a alguien para que alguien pueda enviarle bitcoins. Cuando un remitente pone su dirección en su billetera y le envía una cantidad de Bitcoin, su billetera decodificará la dirección un hash de clave pública. Luego construirá una transacción con una salida que contenga una clave de publicación de script equivalente a esa dirección. El tipo de clave pub script dependerá del tipo de dirección. En este caso, la billetera identificó que el tipo de dirección es compatible con un script hash de pay to public key. Después de recibir Bitcoins a esa dirección, el receptor puede gastarlos a través de una nueva transacción. El nuevo contenido de los campos de entrada de transacción dependerá del tipo de clave pub script que se gastará. En este caso, la billetera construirá una transacción con una entrada que contenga un ScriptSIG con una firma generada usando la misma clave privada que había originado la clave pública que se originó la dirección que recibió Bitcoins previamente. Detalles de la firma de una transacción los veremos en un video futuro. La clave pública citada anteriormente se agregará después de la firma en el campo ScriptSiG. Finalmente, la entrada también hará referencia a la salida de transacción no gastada utilizando el ID de transacción anterior y los campos de índice de salida de transacción anterior como se explicó anteriormente. Ahora aprendamos el importante concepto del conjunto UTXO. Recuerde que UTXO significa salida de transacción no gastada. Bitcoin tiene la característica importante de no permitir el doble gasto. En otras palabras, solo puedes gastar Bitcoins de salidas de transacciones no gastadas. El conjunto UTXO es el conjunto de todos los UTXO existentes actualmente. Este conjunto es almacenado por nodos en una base de datos separada que permite una rápida recuperación por monederos. El conjunto UTXO se actualiza constantemente con cada nueva transacción agregando y eliminando salidas hacia y desde el conjunto. utxos son salidas a las que nunca se hizo referencia en ninguna entrada todavía. Por lo tanto, el conjunto UTXO contiene todas las monedas disponibles para ser gastadas. El número de bitcoins en una dirección es igual a la suma de todos los Bitcoins de todos los UTXOS cuyas claves de pub de script hacen referencia a la dirección decodificada. Entonces el Bitcoin Core Node proporciona un método API llamado list unused que devuelve todos los UTXO que hacen referencia a las direcciones que le pasaste como parámetros. Al usar el método list unused, puede calcular fácilmente el saldo de una dirección y la información de transacción descubierta , como el ID de transacción UTXO y el índice, así como su script pub key. Para que puedas construir entradas de transacción para gastar tus Bitcoins desde el UTXO. Después de gastar el UTXO, se elimina del conjunto UTXO. Ahora veamos un diagrama explicando cómo nuestra aplicación detectará las transacciones entrantes y nos hará saber sobre los bitcoins que recibirán. Esa será la última diapositiva de esta presentación, que ha introducido mucha información compleja. No te preocupes si no lo absorviste todo al principio. A lo largo del curso, estaremos reutilizando la información aprendida para profundizar en ella, así tendremos muchas oportunidades para captarla mejor. Ahora, volvamos al diagrama. Aquí tenemos rectángulos que representan la aplicación son el nodo Bitcoin y la red Bitcoin. Las transacciones son creadas y difundidas por nodos de la red Bitcoin. Estas transacciones, al ser confirmadas, ya están almacenadas en la cadena de bloques. Cuando no están confirmados, permanecen en el templo, una base de datos que contiene todas las transacciones no confirmadas. Cada nodo tiene una copia de las transacciones mentales eventualmente son detectadas por nuestros nodos que ya habían importado nuestras billeteras y direcciones de aplicaciones. A través de cero notificaciones MQ, las transacciones se envían a nuestra aplicación. Cuando nuestra aplicación tenga una billetera cargada, filtrará todas las transacciones de recepción que no contengan ninguna de sus direcciones. Entonces enviará una lista llamada no gastada al nodo, pasando como parámetros todas las direcciones de las transacciones de recepción que quedaron después del filtrado. El nodo devolverá todos los UTXOS relacionados con esas direcciones. Nuestra billetera luego analizará estos UTXO para calcular el saldo de Bitcoin para cada una de sus direcciones. Después mostraremos la información obtenida en la tabla de direcciones. 31. 29 Recepción de bitcoin parte 5 skillshare 2: En este video, implementaremos la lista de clientes no gastados que nos permitirá recopilar información sobre UTXOS después de recibir transacciones. Así que dentro del paquete de cliente nodo punto, vamos a crear la lista de nodos cliente no gastado. Vamos a agregarle una anotación de Servicio. También inyectemos el cliente del nodo en él. Ahora vamos a crear el método de lista no gastada. Devolverá una lista de UTXOS, que es un registro que vamos a crear. Tomará como parámetros una lista de direcciones, y un nombre de billetera. Vamos a crear el registro UTXO en el paquete BYOD w dot domains. El UTXO contendrá los siguientes campos. El ID de TX, que es un acrónimo de ID de transacción. El campo vout, que representa el índice de salida, la dirección, la etiqueta, que no usaremos en este momento. La clave del pub script. La cantidad que representa la cantidad de Bitcoin, las conformaciones que contendrán el número de conformaciones que tiene la transacción UTXOS. El número de conformaciones de una transacción es el número de bloques que se agregaron a la cadena de bloques después de que la transacción se insertó en un bloque y este bloque se agregó a la cadena de bloques. Este número incluye el bloque que contiene esa transacción. Entonces, si una transacción tiene dos confirmaciones, significa que ya estaba incluida en un bloque. Ese bloque se agregó a la cadena de bloques y se agregó otro bloque después de eso. Agreguemos dos campos más. Estos campos no serán utilizados por ahora, pero pueden ser útiles en otro tipo de transacciones que veremos más adelante en el curso. Ellos son el guión de redimir y el guión testigo. Ahora de vuelta a la lista de nodos, el cliente no gastado llamará al cliente nodo make request method y almacenará el resultado en la variable de matriz UTXOS pasará los siguientes parámetros al método. Los tres últimos parámetros formarán parte de la lista de poemas de la API del nodo Bitcoin. El primero es el número mínimo de conformaciones que deben tener los UTXOS de retorno. El segundo es el máximo. Ya que queremos que todos los UTXOS establecerán cero como mínimo y el valor máximo entero como máximo. El tercer parámetro es la lista de direcciones. Ahora, convertiremos la matriz resultante en una lista usando este código y la devolveremos. Ahora volvemos a la transacción recibida oyente. Eliminemos esta línea de código porque era solo para probar. Vamos a probar la lista de nodos cliente no utilizado. Consigamos los UTXOS para estas direcciones. Inyectemos primero al cliente en esta clase, el método list unused pasará la variable addresses. El segundo argumento será el nombre de la billetera de la prueba de Bitcoin receptora. Vamos a copiarlo y usarlo como segundo parámetro. Ahora, agreguemos esta línea para imprimir cada UTXO obtenido en la pantalla. Ahora, ejecutemos nuestro nodo Bitcoin si aún no se está ejecutando. Ahora, vayamos a la prueba de recibir Bitcoin y ejecutarla. En los registros de prueba, vemos que imprimió un UTXO con todos sus datos. Observe que su dirección es la misma que la dirección receptora de nuestra billetera. Rebobinar el video para comprobarlo. El monto es uno, que se espera porque es el mismo monto de Bitcoin enviado y la prueba, tiene cero conformaciones porque ningún bloque recuerda después del nodo desde la transacción. Ahora vamos a eliminar estas líneas porque eran sólo para probar. También eliminemos el cliente inyectado de esta clase. Ahora, agregaremos un filtro a esta transmisión. Queremos procesar solo las transacciones de la cartera actualmente cargada por la aplicación. Este filtro será el responsable de ello. El filtro comprobará si la dirección no está vacía. Si la cartera actual contiene esa dirección. Entonces, vamos a inyectar la cartera actual en esta clase. Entonces llamaremos a las direcciones get como método de cadenas. Después comprobaremos si contiene la dirección. Oh, aquí faltaba una letra S. Ahora vamos a crear el método get addresses como cadenas. Devolverá una lista de cadenas. El valor devuelto resultará de llamar al método get addresses como cadenas en el campo addresses que crearemos. Así que vamos a crear este campo. Tendrá una nueva clase de direcciones como su tipo. Y lo inicializaremos aquí mismo. Vamos a crearlo en el paquete observables. También vamos a crear sus direcciones get como método de cadenas. Primero, agregaremos un campo de direcciones privadas. Será un mapa donde el tipo de clave será un tipo de dirección y el tipo de los valores será otro mapa. El segundo mapa será un HashMap vinculado con cadenas como claves y dirección como el tipo de sus valores. Usaremos esta estructura de datos para almacenar las direcciones. La razón para usar esta estructura de datos es que nos permite separar y consultar las direcciones de la billetera por tipo de dirección. El segundo mapa es un HashMap vinculado porque este tipo de mapa mantiene el orden de inserción. Finalmente, el segundo mapa nos permite consultar la lista de objetos de dirección por sus secuencias de cadenas de direcciones. Ahora en el método get addresses as strings devolverá el siguiente código. La función FlatMap se utilizará para obtener todas las direcciones en el segundo conjunto de claves de mapa y devolver una secuencia que contenga todas ellas. Luego convertiremos la cadena resultante en una lista. Ok, Ahora podemos usar el método get addresses como strings para obtener todas las direcciones creadas para la cartera actual. Pero falta una cosa. También tenemos que rellenar el campo direcciones desde la clase direcciones. Para ello, agregaremos el siguiente código en la actualización. servicio de billetera actual establecerá las direcciones actuales de billetera, pasando las claves de pub extendidas de billetera como parámetro. Ahora vamos a crear el método actual de direcciones de conjunto de billeteras. Llamará al método set addresses del campo addresses, pasando las claves extendidas como parámetro. Después crearemos este método en la clase addresses. Vamos a agregarle el siguiente código. Usaremos la función collect para obtener un mapa de las llaves extendidas del pub. En su interior se agregará una llamada al método de mapa. Su primer argumento construirá un tipo de dirección usando el campo tipo de clave pub extendido. Este argumento define la clave del mapa resultante. El segundo argumento definirá el valor del mapa y contendrá el siguiente código. Nuevamente, al combinar las funciones collect y to map lo configurará como un Hashmap vinculado. Las claves serán las secuencias de cadenas de direcciones de claves de pub extendidas , y los valores estarán allí objetos de dirección correspondientes. Finalmente, se completa la parte filtrante de esta corriente. En el siguiente video, usaremos lo que hemos construido para seguir construyendo la función C receptora de Bitcoins, sí. 32. 30 Recepción de bitcoin parte 6 skillshare 2: En este video, pondremos en proceso los UTXOS de las transacciones que llegan a nuestra billetera. Entonces, en el método de evento no de aplicación, en el oyente de transacción recibida, agreguemos la siguiente declaración if. Si la lista de direcciones no está vacía, entonces llamaremos al método update en el servicio update utxOS que crearemos. Este método tomará como parámetros las direcciones, el nombre de la billetera actual. Inyectemos este servicio en esta clase. Ahora, vamos a crear este servicio en el paquete de servicios punto GUI. Vamos a agregarle la anotación de servicio. Volver a la transacción recibida oyente. Terminemos de inyectar el servicio. Ahora, vamos a crear el método de actualización en el servicio de actualización UTXOS. Añadiremos una anotación asíncrona a este método y la ejecutaremos en el subproceso de servicio de ejecutor predeterminado. La razón para ejecutar este método y otro hilo es que llamará al método API de nodo no gastado de lista, que puede ser lento. Así que lo ejecutaremos asincrónicamente para evitar bloquear la interfaz de usuario. En el método update llamará al método list unused desde el cliente no gastado de la lista de nodos. Inyectemos al cliente en esta clase. Pasaremos las direcciones y el nombre de la billetera como parámetros a la lista. El método no gastado almacenará el resultado de la llamada al método en la variable UTXOS. Ahora, inyectaremos una nueva actualización, servicio actual de direcciones de billetera en esta clase. Vamos a crearlo en el paquete de servicios GUI dots. Terminemos de inyectar el servicio. Después llamaremos al método update pasando UTXOS como parámetro al mismo. Vamos a crear este método. Vamos a agregarle la anotación de servicios. Ahora, agregaremos el siguiente código para crear un mapa donde las claves son direcciones y los valores son listas de UTXOS que contienen esas direcciones. Para ello, llamaremos al método collect en el stream UTXO, le pasaremos los colectores agrupando la llamada MyMethod. Pasando el método de dirección UTXO como su parámetro. Almacenaremos el valor devuelto en la variable de grupo UTXOS. Entonces para cada grupo par de valores clave UTXO establecerá el saldo de dirección correspondiente. Se trata de confirmaciones y se utiliza mercado. Implementemos el método de saldo establecido. Devolverá la suma de todos los montos UTXOS usando este código. Usando el método map to double en el flujo de lista UTXO, se obtendrá un stream con todas las cantidades UTXO de la lista UTXO. Para obtener su suma simplemente se llamará al método sum en el resultado. Ahora, vamos a inyectar la cartera actual en esta clase. Entonces llamaremos al método balanceado de direcciones de conjunto de billetera actual , que creará pasar la dirección y la suma como sus parámetros. Vamos a crearlo. En su interior se llamará al método de dirección del conjunto de direcciones balanceado, pasándole los mismos parámetros. Entonces crearemos este método. En su interior se llamará a las direcciones get como método de mapa, que creará. Vamos a crearlo. Devolverá un mapa donde las claves son direcciones, cadenas y los valores se abordan como objetos. Mediante el uso del siguiente código se devolverá un mapa que contiene todas las direcciones. Al llamar al método de cadena en las direcciones, los valores se obtendrá un flujo que contiene todos los mapas del campo privado de direcciones. Entonces con esta llamada al método FlatMap se convertirá el flujo de mapas en un flujo de entradas de mapa. Finalmente, utilizando el método collect en el stream resultante y el método de dos mapas con estos parámetros se obtendrá el mapa deseado. En el resultado de las direcciones get como map call llamará al método get para obtener un objeto address por su cadena de direcciones. Después estableceremos el saldo de direcciones a la variable sum. Ahora, vamos a crear el método set balance en el registro de direcciones. Ups, no podemos agregar setters en un registro, así que tendremos que convertir el registro de dirección en una clase. Hagámoslo con un poco de ayuda de nuestro IDE. Eliminemos estos métodos porque no los vamos a necesitar. Vamos a crear el centro de equilibrio ahora. Y eliminar la palabra clave final aquí. En el generador secuencial de direcciones. Vamos a agregar cero como tercer parámetro en la instanciación de direcciones aquí. Cambiemos también el nombre de los getters, haciéndolos comenzar con get. Ahora en el servicio de actualización de direcciones de billetera actual, vamos a crear el método de confirmaciones establecidas. Confirmación. En este caso, nos referiremos al saldo de direcciones y se definirá como igual al número de conformaciones del UTXO con menos conformaciones para esa dirección. Por ejemplo, digamos que una dirección tiene un saldo de dos Bitcoins, cada Bitcoin proviene de una transacción diferente. Una de estas transacciones tiene dos confirmaciones, la otra solo tiene una. En este caso, consideraremos que el saldo de direcciones tiene una conformación. Para lograrlo, usaremos el siguiente código. Obtendremos un stream que contiene todas las confirmaciones de la lista de UTXOS pasada. Para obtener este flujo, llamaremos al método map too long en el flujo de lista UTXO, pasando como parámetro la referencia del método de confirmaciones UTXO . Entonces mediante el uso del método Min y el método bueno es largo devolverá el número mínimo de confirmaciones en el stream y lo almacenará en la variable de confirmaciones. Luego pasaremos las confirmaciones y las variables de dirección a la llamada actual del método de confirmaciones de direcciones del conjunto de billetera. Ahora vamos a crear este método en la clase de billetera actual. Llamará al método de confirmaciones de direcciones del conjunto de direcciones, pasando los mismos parámetros que recibieron. Vamos a crear este método en la clase addresses. Usaremos el método get addresses como método de mapa para obtener la dirección y establecer sus conformaciones. Ahora, vamos a crear el método set confirmations en la clase address. Lo usaremos para establecer el campo de confirmaciones que crearemos. Vamos a crear este campo y agregarlo al constructor. Entonces agreguemos este parámetro a la clase de generador secuencial direcciones en la instanciación de direcciones. Por último, vamos a crear el método de marca se utiliza en el servicio de actualización de direcciones de cartera actual. Uno de los objetivos de nuestro monedero y muchos otros es evitar reutilizar direcciones al recibir Bitcoins. Por razones de privacidad. Para ello, primero debemos comercializar vestidos que tenían transacciones a él como se usaban. La marca como método utilizado se utilizará para esa visión. Se llamará al actual vestido de mercado monedero. Como método utilizado se creará pasando la dirección como su parámetro. Vamos a crearlo. En su interior llamará a la marca se usa método de la clase de direcciones pasando la dirección a la misma. Entonces crearemos este método. En su interior utilizará las direcciones get como método matemático para obtener la dirección y se utiliza el mercado. Por último, vamos a crear el método mark se utiliza en la clase address. Aquí simplemente establecerá el combustible usado es cierto. Vamos a crear este campo en esta clase. 33. 31 Recepción de bitcoin parte 7 skillshare 2: En este video, finalmente conectaremos todo lo que hicimos en las últimas lecciones para mostrar información de nuestras direcciones en la pantalla. Así que en el paquete observables se creará la clase de fila de direcciones. Como su nombre indica, esta clase modelará una fila en la tabla de direcciones. Vamos a crear los siguientes campos en esta clase, cada uno para una columna en la tabla de direcciones. El primer campo será una propiedad de cadena llamada balance, instanciará aquí con una nueva propiedad de cadena simple. El siguiente campo será una propiedad larga llamada confirmaciones, y se instanciará con una nueva propiedad larga simple. El último campo será una propiedad de cadena llamada address. Se instanciará con una nueva propiedad de cadena simple. Ahora, con la ayuda del IDE, vamos a crear getters para cada propiedad. Observe que al hacer getters para campos de propiedad Java FX, el IDE crea dos getters, uno para la propiedad y otro para el contenido de la propiedad. Ahora, vamos a crear el siguiente constructor para esta clase. Bien, ahora que hemos modelado la fila de direcciones, vamos a crear código para rellenarla al actualizar nuestras direcciones. Para ello, vayamos al servicio de actualización actual de direcciones de monedero. En el método update, después de marcar la dirección como utilizada, llamemos al método set address row en la billetera actual, pasando la dirección como parámetro. Entonces vamos a crear el método set address row. Para implementar este método se agregará el campo de filas de direcciones a esta clase. Vamos a crear la clase de filas de direcciones en el paquete observables. Vamos a instanciarlo aquí. Ahora vamos a llamar al método set address row en la propiedad address rows le pasará un objeto address. Este objeto se obtendrá del campo addresses usando el método get addressed que crearemos pasándole la cadena de direcciones. Para crear este método simplemente seleccionaremos este fragmento de código y extraerá un método de él usando el ID. Sustituyamos todas las ocurrencias de código con este método, y haremos público el método generado. Ahora volvemos a la actual clase de cartera. Vamos a crear el método set address row en la clase address rows. Para ello, crearemos una variable de fila de dirección llamando al método en la clase address row, pasando el objeto address como parámetro. Vamos a crear el método form en la clase de fila de direcciones. Devolverá una nueva fila de direcciones, instanciándola con estos parámetros. Vamos a crear el método de buenas confirmaciones en la clase address. Y ahora podemos usarlo aquí. Observe que aquí simplemente estamos creando un objeto de fila de direcciones convirtiendo los valores de campo de dirección en los valores de campo de fila de dirección. Volver a la clase de filas de direcciones. Crearemos el campo de conjunto de carreteras de dirección en esta clase. Será un conjunto observable con la fila de direcciones como parámetro de tipo. Lo instanciará aquí con un nuevo envoltorio de conjunto observable, pasando un nuevo conjunto hash vinculado a su constructor. Este objeto publicará un evento por cada nueva dirección insertada o eliminada y será necesario actualizar la tabla de direcciones a medida que la cartera actual reciba nuevas transacciones. Ahora llamaremos al método address row set remove, pasando la fila de direcciones como su parámetro. Después llamaremos al método add en él, pasando la misma fila de direcciones que su parámetro. Quizás te preguntes por qué estamos eliminando y agregando la misma fila de direcciones en el conjunto. Bueno, esto es un poco pirateo. Si no eliminamos primero la fila de direcciones e insertamos una fila de direcciones que ya está en el conjunto. El conjunto observable no publicará ningún evento que indique que se le agregó una fila de direcciones. Hay otra cosa que tenemos que hacer para que esto funcione. Cuando eliminamos una fila de direcciones del conjunto usando el método remove, este método utilizará el método equals de la fila de direcciones para definir qué fila de direcciones eliminará del conjunto. Consideraremos que las dos filas de vestir son iguales si tienen la misma dirección. Por lo tanto, debemos implementar el método equals en la clase de fila de direcciones. Hagámoslo. Añadiremos los métodos de código equals y hash usando esta función IDE. Asegúrese de que esta casilla de verificación esté activada para generar métodos usando getters. Ahora, elegiremos usar solo el campo address para generar el método equals. Y el mismo campo para generar el método hashCode y seleccionar el campo address aquí para definirlo como no nulo. Bien, el IDE ha generado los métodos de código equals y hash. Ahora vamos a la tabla de direcciones. Fxml agregará ID de FX a cada etiqueta de columna de tabla. Las direcciones. El controlador de tabla necesitará estos ID de FX para unir y manipular estas columnas más adelante. Primero la dirección de la columna, luego el saldo de la columna, y finalmente las conformaciones de columna. Ahora vamos a ir a la tabla de direcciones el controlador agregará los siguientes campos, cada uno correspondiente a una etiqueta con un ID de ética en la tabla de direcciones, FXML. Los nombres de estos campos deben ser iguales a los FX ID de las etiquetas. Están destinados a. Primero la tabla de direcciones, luego la dirección de la columna, el saldo de la columna y las confirmaciones de columna. Ahora agregaremos el método inicializado a esta clase. Recuerde que los métodos inicializados en los controladores Java FX se llaman Cuando el framework está inicializando estos controladores. En este método, agregaremos código que vinculará la tabla de direcciones y sus columnas con nuestro rol de dirección observables. Para ello, llamaremos al método set items en la tabla de direcciones ya que su argumento pasará una nueva lista filtrada. Esto es necesario porque queremos mostrar solo direcciones con un equilibrado mayor que cero en la tabla de direcciones. Como el primer parámetro de lista filtrada pasará las filas de direcciones observables actuales de la billetera. Entonces, vamos a inyectar la cartera actual en esta clase. Entonces llamaremos al método get observable address rows en él. Vamos a crear este método. Devolverá una lista observable con la fila de direcciones como parámetro de tipo. Luego devolveremos la llamada al método de filas de direcciones observables buenas en el campo de filas de direcciones. Vamos a crear este método en la clase de filas de direcciones. En su interior devolverá el campo de lista de filas de direcciones que vamos a crear. Vamos a crearlo. Este campo se instanciará aquí con un nuevo envoltorio de lista observable pasando una lista enlazada como parámetro. Ahora, tenemos que hacer que la lista observable responda a inserciones y eliminaciones de filas de direcciones en el conjunto de filas de direcciones. Eso lo haremos en el constructor de la clase. Primero, crearemos una variable de escucha de cambio de conjunto. Lo estableceremos como esta función lambda. El parámetro change aquí representa una inserción o eliminación de una fila de direcciones en el conjunto. Si el cambio fue una eliminación, entonces eliminaremos el elemento removido de la lista de filas de direcciones. Si el cambio fue una inserción. Luego agregaremos el elemento agregado a la lista de roles de dirección. Finalmente, agregaremos este oyente al conjunto de filas de direcciones usando este método. Ahora volvamos al controlador de la tabla de direcciones. El segundo parámetro de la lista filtrada se utiliza como condición de filtro para mostrar filas. Será una función lambda con un parámetro address rho. El cuerpo de la función será este código que verificará si el saldo de fila de dirección es mayor que cero. De esa manera, logramos nuestro objetivo de mostrar únicamente direcciones con un equilibrado superior a cero. Ahora, para cada campo de columna, tenemos que establecer una fábrica de valores de celda que se utilizará para poblar cada celda de la tabla de direcciones. Para ello, usaremos el siguiente código. La fábrica de valor de propiedad se utilizará para obtener cada dirección propiedad real y vincular su valor a su celda correspondiente. Sabe qué dirección inmobiliaria queremos enlazar a la columna haciendo coincidir el nombre que estamos pasando como parámetro con el nombre de la propiedad. Hay una cosa más que debemos hacer para que nuestra función de recibir Bitcoin funcione correctamente. Pasemos a la clase de billetera actual en el método set addresses, que se llama cuando se crea una nueva billetera, tenemos que incluir este código para asegurarnos de que la dirección elevó de una previamente cartera creada se borra. Llamaremos al método address rows clear, que creará. Para ello, vamos a crearlo. Aquí. Simplemente llamaremos al método clear en el conjunto de filas de direcciones y la lista de filas de direcciones. Ahora probemos nuestra función. Asegúrate de que tu nodo central de Bitcoin esté funcionando. Vayamos a la prueba de recibir Bitcoin y ejecutarla. Genial, funcionó. Observe que la primera fila de la tabla de direcciones se llenó correctamente con un saldo de un Bitcoin como se esperaba. Buen trabajo. En los próximos videos, agregaremos más casos de prueba para asegurarnos de que nuestra función de recepción de Bitcoin funcione correctamente en diferentes escenarios. 34. 32 Recepción de bitcoin parte 8 skillshare 2: En este video, agregaremos más casos de prueba para asegurarnos de que nuestra función de recepción de Bitcoin funcione correctamente en diferentes escenarios. El primer escenario adicional probaremos si la misma dirección puede recibir Bitcoins de dos transacciones, una Bitcoin de cada una. Comprobaremos el saldo de la dirección se actualiza a dos bitcoins. Entonces vamos a copiar el contenido de este método y pegarlo a continuación. Modifiquemos el nombre de la prueba para recibir Bitcoins en dos transacciones a la misma dirección. Ahora, seleccionemos este código y extraigamos un método de él con la ayuda del id vamos a nombrarlo, enviar Bitcoin y peso. Llamaremos a este método dos veces ya que queremos enviar a transacciones a esta dirección. Modifiquemos el método send Bitcoin in weight incluyendo el siguiente código. Comprobaremos si la dirección en la primera fila de la tabla tiene un parámetro balanceado igual al monto total esperado. Agreguemos este parámetro a la firma del método. Tendrá un valor predeterminado de 1.0. En esta llamada al método, agreguemos 2.0 como segundo parámetro, ya que esperamos que el saldo de direcciones sea igual a dos. Agreguemos dos al nombre de la billetera. Hay un problema con nuestro entorno de prueba. En la prueba reg, solo es posible extraer 15 mil bloques con recompensas de bloque. Por lo tanto, en este método, es demasiado minar 1,000 bloques al llamar al método generate to address. Solo llamémoslo si el saldo de la billetera de prueba es menor 50 y generará solo 150 bloques por cada llamada. De esa manera, evitamos la necesidad de restablecer nuestro entorno de prueba reg con demasiada frecuencia. También sustituyamos este código con el método send Bitcoin and wait. Ahora, hagamos que nuestras pruebas sean un poco más resistentes a las condiciones de la carrera. Me he dado cuenta de que a veces estas pruebas envían bitcoins a nuestras billeteras de aplicaciones antes de que estuvieran completamente cargadas. Por lo tanto, estas transacciones no fueron capturadas por la aplicación y las pruebas fallan por ese motivo. Entonces después de crear una billetera y antes de enviarles Bitcoins, llamemos al método sleep con estos parámetros. La llamada al método sleep hará que la aplicación espere 10 s antes enviar Bitcoins el tiempo suficiente para que la nueva billetera se cargue por completo. Dependiendo de su computadora, es posible que necesite aumentar la constante de tiempo de espera. Ahora, antes de ejecutar las pruebas, restableceré mi entorno de prueba reg. Necesito hacer eso porque ya generó 15 mil bloques y la generación de bloques ya no está produciendo Bitcoins. Entonces iré a la carpeta donde está almacenada la cadena de bloques y eliminaré la carpeta reg test dentro de ella. En tu caso, puedes encontrar qué carpeta se encuentra comprobando el valor DIR de datos en tu archivo bitcoin.com. Ahora, ejecutemos nuestro nodo Bitcoin y ejecutemos nuestras pruebas de recepción de Bitcoin. Genial, las pruebas han pasado. Cuando recibamos Bitcoins en nuestra billetera, queremos que se cambie la siguiente dirección de recepción. De esa manera evitamos reutilizar direcciones. Es importante usar solo una dirección para recibir transacciones para que un tercero pueda rastrear fácilmente cuántos Bitcoins tiene y con qué direcciones realiza transacciones. Para cubrir este escenario, vamos a crear la siguiente prueba. Copia la última prueba y pégala a continuación. Vamos a cambiarle el nombre a debería recibir Bitcoins en dos transacciones, dos direcciones diferentes. Cambiemos el nombre de la billetera creada a mi billetera de prueba tres. Ahora antes de la segunda llamada al método de envío de Bitcoin y espera, agreguemos este código para volver a consultar el campo de dirección de recepción y almacenar su contenido en la siguiente variable de dirección. Ahora, cambie el primer parámetro de este método a la siguiente variable de dirección. Y esperamos que el monto total de Bitcoin para esta dirección sea igual a 1.0. Además, esperamos que el tamaño de los elementos de la tabla sea igual a 21 filas por cada dirección. Entonces, modifiquemos este método para aceptar el tamaño esperado de la tabla como parámetro. Vamos a agregarle este parámetro con un valor predeterminado de uno. Sustituirá este valor aquí para esperar a que el número de filas de la tabla sea igual a él. Y sustituiremos el índice de ítems de punto de tabla por el tamaño total esperado menos uno para esperar a que la última fila del saldo de la tabla sea igual al monto total esperado para esa fila. Por último, vamos a parametrizar el tercer argumento de este método llamado a dos. Realicemos nuestras pruebas. Como se esperaba. La tercera prueba falló porque aún no hemos implementado la función de cambiar la dirección de recepción después de usarla. Hagámoslo ahora. Así que vayamos al servicio de actualización de direcciones de monedero actual. Dentro de esto para cada bloque, llamemos al método de dirección de recepción de actualización que crearemos. Tomará la dirección como su parámetro. Vamos a crearlo. Lo primero que haremos es llamar al método de tipo get addressed en la billetera actual. Al pasar la dirección como su parámetro, se almacenará el resultado de la llamada al método en la variable de tipo de dirección. Es importante conocer el tipo de dirección de la dirección sustituida, ya que tiene que ser sustituida por una dirección del mismo tipo. Entonces, vamos a crear este método en la clase de billetera actual. Simplemente llamará a las direcciones get addressed type method. Crearemos pasando la dirección como su parámetro. Vamos a crearlo. Ahora. Llamaremos al método get addressed y devolveremos su tipo de dirección. Vamos a crear el método get address type en la clase address. En su interior devolverá el campo de tipo de dirección que vamos a crear. Vamos a crear este campo y agregarlo al constructor. También arreglemos el generador secuencial de direcciones para agregar el último argumento a la instanciación de dirección. Vamos a agregar este tipo de dirección como parámetro a este método. E incluiremos el tipo de dirección en esta llamada al método llamando al valor de método en la clase de tipo dirección. Ahora de vuelta al servicio Actualizar direcciones de billetera actuales calculará el valor del siguiente índice de direcciones llamando al método fine next address index en la billetera actual, pasando la dirección type ya que su parámetro almacenará el resultado de la llamada al método en la siguiente variable de índice de dirección. Vamos a crear este método. Aquí. Llamaremos al índice de dirección siguiente fino en el campo direcciones, pasando el tipo de dirección como parámetro. Vamos a crear este método en la clase de direcciones con el siguiente código, obtendrá la última dirección utilizada en almacenarlo en la variable address. Obtendrá todos esos objetos de vestir con el tipo de dirección dado y obtendrá una transmisión de ella. Después ordenaremos el flujo obtenido usando el método ordenado con los siguientes parámetros. Se utilizará el método de comparación de puntos del comparador, pasando el método address get indexed como primer parámetro y el comparador de orden inverso como el segundo. De esa manera obtendremos un flujo de direcciones ordenado en sentido inverso por sus índices. Ahora, filtraremos la secuencia para obtener una cadena que contenga solo direcciones usadas. Para ello, vamos a crear un getter para el campo usado en la clase address. Usaron getter se llama se usa porque así es como el IDE nombra getters booleanos de vuelta a la clase addresses pasarán las direcciones utilizadas método como el prompt a la llamada al método filter. Ahora llamaremos al primer método fino sobre el resultado. Para obtener la primera dirección utilizada y la secuencia ordenada invertida, que es igual a la última utilizada para direccionar. ¿Qué pasa si no se encuentran direcciones usadas? En este caso, usaremos el método or else para devolver null. Añadiremos la siguiente declaración if. Si la dirección obtenida es nula, entonces volveremos cero como el siguiente índice. Si no es así, devolveremos el último índice de direcciones más uno. Ahora, de vuelta al servicio Actualizar direcciones de billetera actuales , obtendrá la siguiente dirección llamando al método get address ID en la billetera actual. Pasaremos el siguiente índice de dirección y el tipo de dirección como parámetros. Vamos a crear este método en la cartera actual. Volverán, obtienen la llamada al método de identificación de dirección en el campo direcciones, pasando los mismos argumentos recibidos que sus parámetros. Vamos a crear este método en la clase addresses. Obtendrá todos esos objetos de vestir con el tipo de dirección dado. Después lo convertiremos en una lista. Entonces obtendremos la dirección por índice. Para ello, necesitamos cambiar el tipo de índice de dirección a un objeto largo, no solo de tipo primitivo. Y luego llamaremos al valor int, pasándolo como el parámetro getMethod. Ahora devolveremos la cadena de dirección de la dirección obtenida. Ahora, de vuelta al servicio Actualizar direcciones de billetera actuales simplemente configurará la dirección de recepción de billetera actual como la siguiente dirección obtenida. Hagamos una cosa más antes de probar nuestro código. Recuerda que el codón, esta clase se ejecutará en un nuevo hilo. En Java FX, es una buena práctica ejecutar código que modifique la interfaz de usuario solo en el hilo principal. Para ello, llamemos al método platform dot run later pasándole una función Lambda. Movamos estas dos líneas al cuerpo de la función lambda ya que provocan cambios que afectarán a la IU. Ahora, volvamos a ejecutar nuestras pruebas de recepción de Bitcoin. Genial. El campo de dirección de recepción se actualizó después recibir fondos y las pruebas han pasado. En el siguiente video, seguiremos mejorando nuestras pruebas y agregaremos un escenario de prueba más. C, sí. 35. 33 Recibiendo bitcoin parte 9 skillshare 2: En este video, seguiremos mejorando nuestras pruebas y agregaremos un escenario de prueba más importante para la función receptora de Bitcoin. Una cosa falta en nuestras pruebas. Aún no sabemos si se están generando las direcciones correctas se están generando y si están respetando la secuencia del índice de ruta de derivación. Para comprobarlo, vamos a crear la dirección es método válido. Entonces bloque de la primera prueba llamada la dirección es método válido pasando la dirección, la semilla mnemotécnica y el índice de dirección esperado, que en este caso es cero como sus parámetros. Vamos a crear este método. Devolverá un booleano. Vamos a establecer los nombres de parámetros correctos. Aquí. Crearemos un nuevo objeto semilla mnemotécnico y lo almacenaremos en la variable semilla mnemónica. Cambiemos el nombre del parámetro de semilla mnemotécnico a la cadena de semillas mnemotécnicas. Ahora instanciaremos el objeto semilla mnemotécnico pasando la cadena semilla mnemónica como parámetro constructor. Ahora, vamos a crear la clave maestra con el siguiente código. Llamará al método de dos claves maestras en el objeto semilla mnemotécnico, pasando una cadena vacía como primer parámetro y el prefijo privado de red principal como el segundo. Ahora vamos a crear la cadena extendida de la clave pub con el siguiente código. Usaremos el servicio extendido de llaves de pub. Así que vamos a inyectarlo en esta clase. Entonces llamaremos al método create en él, pasando la clave maestra como su primer parámetro. El segundo parámetro será una concatenación entre parte de la ruta de derivación de dirección de segmento y el parámetro de índice. Cambiemos el tipo de parámetro index a la clase integer, así podemos llamar al método toString en él. El tercer parámetro será la constante Segway tipo dirección. Entonces llamaremos al método get key sobre el resultado. Ahora, obtendremos el objeto de clave pub extendido de la biblioteca Java de Bitcoin usando la clave de pub extendida en el método serializado, pasando la cadena de clave pub extendida como su parámetro obtendrá la dirección esperada usando el generador de direcciones de segmento. Vamos a inyectarlo en esta clase. Luego llamaremos al método generate en él, pasando la clave pub extendida como su parámetro. Finalmente, devolveremos el resultado de comparar si la dirección esperada es igual al parámetro address. Ahora vamos a agregar la dirección es válida llamada al método para verificar las direcciones en los otros métodos de esta clase. En este método, vamos a agregarlo dos veces. La segunda vez comprobaremos si la siguiente dirección es igual a la dirección esperada con el índice uno. Realicemos nuestras pruebas. Genial, las pruebas han pasado. Ahora sabemos que las direcciones se están generando correctamente. Ahora vamos a crear otra prueba. La siguiente prueba intentará transferir más transacciones que el número de direcciones generadas. Recuerda que hemos establecido el número inicial de direcciones generadas en 20. Por lo que debemos verificar qué sucede cuando se utilizan todas las direcciones generadas inicialmente. Pero ejecutar una prueba con 20 transacciones llevaría mucho tiempo. Entonces cambiaremos el número inicial de direcciones generadas en el entorno de prueba a tres más tarde para acelerar las cosas. Así que vamos a copiar este método y pegarlo a continuación. Cambiar su nombre a debería recibir Bitcoin en siete transacciones a diferentes direcciones con tres direcciones generadas en nuestra billetera y siete transacciones en esta prueba, nuestra billetera necesitaría para generar cuatro direcciones más que el número inicial para que pase esta prueba. Cambiemos el nombre de la billetera creada por mi billetera de prueba. Por ahora, crearemos un archivo de propiedades para el entorno de prueba para cambiar el número inicial de direcciones generadas para nuestras pruebas. Así que vamos a crear una ruta de recursos dentro del paquete de prueba. Seleccione la opción Recursos a continuación. En su interior se creará un archivo llamado application test dot properties. Copiaremos el contenido de nuestro archivo de propiedades de punto de aplicación y lo pegaremos aquí. Ahora vamos a establecer el número inicial de propiedad de direcciones generadas en tres. Ahora vamos a la clase de configuración de direcciones. El número inicial de direcciones generadas método actualmente está devolviendo 20 inyectará este valor en esta clase desde el archivo de propiedades utilizando esta anotación de valor y este campo privado. Ahora en este método sólo devolverá el campo creado. Ahora para usar propiedades de la aplicación probar archivos de propiedades de punto en nuestras pruebas. Vamos a la clase de prueba GUI. Añádele esta anotación. Bien, ahora cada archivo de prueba que extienda la prueba GUI obtendrá sus propiedades del archivo de propiedades de punto de prueba de aplicación. Ahora volvamos a nuestra última prueba. Cambiemos el nombre de esta variable a la primera dirección. El nombre de esta variable a la segunda dirección. Ahora copiemos estas líneas y generemos cuatro transacciones más para formar direcciones más recién generadas, modificando su código en consecuencia. Cambiemos el tamaño esperado de la fila de la tabla a siete. Copiemos estas líneas también para validar todas las direcciones generadas en la prueba. Cambiemos los parámetros de los métodos según sea necesario. Ahora, hagamos nuestras pruebas. Como se esperaba. La última prueba ha fallado después de la tercera transacción que ocurrió porque la billetera no pudo encontrar la cuarta dirección ya que generó solo las tres primeras direcciones. En el siguiente video, lo arreglaremos. Antes de terminar el video, agreguemos el número inicial de propiedades de direcciones generadas al archivo de propiedades de punto de la aplicación. Vamos a establecerlo en 20 para que la billetera funcione como antes en el entorno no de prueba. 36. 34 Recepción de bitcoin parte 10 skillshare 2: En este video, haremos nuestro último pase de prueba creado. Para ello, vayamos al servicio de actualización actual de direcciones de monedero. En este método, agreguemos la siguiente declaración if. Después de calcular el siguiente índice de dirección. Dentro de la sentencia if, los llamaremos método must import addresses pasando el siguiente índice de direcciones y el tipo de dirección. Vamos a crear este método. Solo importará direcciones si el siguiente índice de direcciones es igual al número total de direcciones en la billetera actual con un tipo de dirección dado. Si ese es el caso, significa que nos quedamos sin direcciones y así no podemos rellenar la siguiente dirección para nuestra billetera sin crear más direcciones. Dentro de este método devolverá el resultado de verificar si el siguiente índice de direcciones es igual al actual wallet get addresses count method call pasará el tipo de dirección a este método. Y vamos a crear este método. Este método devolverá un int y devolverá las direcciones, obtendrá adresses count method call, pasando el tipo de dirección como su parámetro. Vamos a crear este método. Aquí simplemente obtendremos todas las direcciones con el tipo de dirección dado en una lista y devolveremos el tamaño de la lista al servicio Actualizar direcciones de billetera actuales. En el bloque if primero obtendrá las billeteras actuales extendidas las claves de pub, y las almacenará en una variable. Vamos a crear este método. Aquí. Regresaremos el campo extendido de llaves del pub. Vamos a crearlo. También agreguemos un setter para este campo. Llamaremos a este conjunto o en el método de actualización del servicio de billetera actual de actualización. Pasando las billeteras le extendieron las llaves del pub. Ahora volvamos al servicio Actualizar direcciones de monedero actuales. Llamaremos al método add addresses en el servicio de direcciones ADD. Pasando las claves de pub extendidas previamente obtenidas como su primer parámetro y el siguiente índice de dirección como su segundo parámetro. Inyectemos este servicio en esta clase. Vamos a crear este servicio y el paquete de servicios API. Vamos a agregarle la anotación de servicio. Ahora, terminemos de inyectar este servicio a esta clase. Y vamos a crear este método en el servicio de direcciones de anuncios. Cambiemos este nombre de parámetro a from index. Lo que planeamos hacer ahora es generar direcciones para las claves de pub extendidas que se pasaron como parámetros. El número de direcciones generadas será igual al número inicial de direcciones generadas campo inyectado. Y el índice de derivación generado por la primera dirección será determinado por la variable de índice firme, por ejemplo, supongamos que el número inicial de direcciones generadas es igual a 20 y la variable de índice from es igual a 20. En ese caso, este método generará vestidos con un índice de derivación de 20 a 39. Para ello, por cada llave de pub extendida. Llamaremos al método add addresses, pasando la clave y el parámetro from index. Quitemos esta letra S. Ahora, vamos a crear este método de agregar direcciones privadas. Llamará al método add addresses en la clave pub extendida como su parámetro. Utilizaremos el generador secuencial de direcciones. Entonces vamos a inyectarlo en esta clase. Llamaremos al método generate en el generador secuencial de direcciones, pasando la clave de pub extendida, el tipo de clave pub extendida y la variable from index como sus parámetros. Pasemos a la implementación del método generate. La cambiará para generar direcciones con índices de derivación utilizando el parámetro from index. Entonces agreguemos desde index como su tercer parámetro. Aquí en el método range call agregará la variable from index como su primer parámetro. Y la suma del parámetro from index y el número inicial de direcciones generadas como el segundo. Ahora volvamos al servicio de direcciones ADD. Vamos a crear el método de direcciones de anuncios en la clase de clave de pub extendida. Arreglemos este nombre de parámetro. Aquí. Llamaremos al método addresses add all pasándole el parámetro addresses. Hay un problema con este código. El campo direcciones es de tipo list, que es inmutable. Eso significa que cuando intentemos agregarle elementos a través del método add all, arrojará un error. Entonces vamos a cambiarlo al tipo ArrayList, que es mutable. Hagámoslo también definitivo e instanciado aquí. Cambiemos también el getter de direcciones y el método addresses para obtener y establecer una ArrayList. También eliminemos el método set addresses ya que ya no lo usaremos. Volver al servicio de agregar direcciones. Vamos a envolver el resultado de llamada al método generate en una nueva ArrayList, ya que el método de direcciones de anuncios ahora acepta solo una ArrayList. Ahora vamos a ejecutar factores que crean el servicio de monedero. Ya que hemos hecho cambios que afectaron. Primero, eliminemos el servicio generador secuencial de direcciones de esta clase. También eliminemos este método. Eliminemos esta línea de código. Usaremos el servicio de agregar direcciones para agregar direcciones a las llaves de pub extendidas. Entonces vamos a inyectarlo en esta clase. Y llamemos al método add addresses en él, pasando las claves de pub extendidas y cero como sus parámetros. Terminemos de inyectarlo en esta clase. Ahora volvamos al servicio Actualizar direcciones de monedero actuales. Llamaremos al método set addresses en la billetera actual, pasando las claves de pub extendidas como su parámetro. Vamos a eliminar las filas de direcciones método clear call en los métodos set addresses ya que no queremos eliminar ninguna fila de tabla de direcciones después de establecer estas direcciones. En su lugar, vamos a crear un método llamado clear address rows, que hará eso. Luego, en el método de actualización del servicio de billetera actual de actualización, llamaremos a este método para borrar las filas de direcciones solo después de agregar una nueva billetera. Ahora de vuelta al servicio Actualizar direcciones actuales de billetera obtendrá todas las direcciones recién generadas en la billetera actual y las almacenará en esta variable. Para obtener las direcciones se llamará al método get addresses como cadenas en la billetera actual. Pasando el siguiente índice de dirección como su primer parámetro. Y la suma del siguiente índice de direcciones y el número inicial de direcciones generadas campo como segundo parámetro. Inyectemos este campo en esta clase. Vamos a agregar la anotación calificador para usar el bean definido en la clase de configuración de direcciones para inyectar el valor deseado en este parámetro. Ahora, vamos a crear este método. Cambiemos estos nombres de parámetros a de índice dos índice. Este método devolverá las direcciones, obtendrá direcciones como método de cadenas de llamada pasando los mismos parámetros que recibió. Vamos a crear este método en la clase addresses. Este método devolverá todas sus direcciones con índices entre los parámetros del índice dos índice, pero sin incluir la escalera. Para ello, devolverá el siguiente código. Usaremos el método FlatMap para convertir todas las direcciones en un flujo de objetos de dirección. Luego filtraremos el flujo para que solo devuelvan direcciones con índice mayor o igual que la variable de índice firme y menor que las dos variables de índice. Después llamaremos a un mapa sobre el resultado para devolver un flujo de cadenas de direcciones. Finalmente, convertiremos el resultado a una lista y lo devolveremos. Ahora, de vuelta al servicio Actualizar direcciones de billetera actuales , usaremos los clientes de direcciones de importación múltiple de nodo para importar las direcciones recién generadas en nuestro nodo Bitcoin. Recuerda que esto es necesario porque es necesario que el nodo conozca nuestras direcciones para que pueda enviar transacciones relacionadas a nuestra cartera de aplicaciones. Entonces vamos a inyectarlo en esta clase. Ahora llamaremos al método de direcciones de entrada en él, pasando el nombre de la billetera actual, las cadenas de direcciones y una nueva fecha como sus parámetros. Genial, nuestra función de rotación de direcciones debería funcionar ahora, incluso después de que se utilicen todas las direcciones generadas inicialmente. Pero manejemos otro tema aquí. Estamos estableciendo la siguiente dirección como la dirección de recepción en nuestra billetera. Incluso si se trata de tipo de dirección es un cambio de dirección. Vamos a arreglar eso. Ya que queremos solo direcciones con el tipo Segway, no el tipo de cambio Segway se dice como direcciones receptoras en nuestra billetera. Entonces agregaremos esta declaración if. Si el tipo de dirección es igual a la constante de dirección principal, lo que la establecerá en segue. Ahora. Luego estableceremos la siguiente dirección como la siguiente dirección de recepción en la billetera actual. Una cosa más, vamos a eliminar esta plataforma run later call will call the run later method only wrapping the code that will really change the UI. Así que vamos a usarlo para envolver sólo el actual conjunto de cartera de direcciones roll-call. También utilicémoslo para envolver el conjunto de billetera actual recibiendo la llamada al método de dirección. De esa manera, evitamos bloquear la interfaz de usuario mientras comunicamos con nuestro nodo Bitcoin en la llamada al método import addresses. Ahora vamos al controlador de la tabla de direcciones. He notado que el TableView a veces no se actualiza para reflejar el estado real de sus filas. Para solucionarlo, agreguemos este código a este método. Agregará un oyente a las filas actuales de direcciones observables de la billetera. En el cuerpo de esta lambda simplemente llamará al método refresh en la tabla de direcciones. De esa manera, por cada actualización en nuestras direcciones de billetera, garantizamos que la vista de tabla, actualizaremos y mostraremos la información actual de nuestras direcciones de billetera en la pantalla. Ahora, vayamos a la prueba del generador secuencial de direcciones y agreguemos cero como tercer parámetro del método de generación para que esta prueba siga funcionando. También arreglemos la prueba del servicio de creación de billetera. En el método de configuración, vamos a instanciar el servicio de direcciones ADD, pasando el generador secuencial de direcciones como su parámetro. Y sustituyamos el tercer parámetro del servicio create wallet por el servicio de direcciones ADD. Ahora, en la última prueba receptora de Bitcoin, hagamos un pequeño cambio. Después de enviar Bitcoin a la tercera dirección. Vamos a agregar el método dormido llamada pasando timeout y seconds como sus argumentos. También agreguemos la misma llamada después de enviar Bitcoins a la sexta dirección. El motivo de estas llamadas es que antes enviar Bitcoins a las direcciones cuarta y séptima, tenemos que generarlos e importarlos a nuestros nodos antes de aceptar transacciones a ellos. Y el proceso de importación lleva algún tiempo. Por fin ejecutemos todas nuestras pruebas de aplicación. Genial, todas las pruebas han pasado. Finalmente terminamos los conceptos básicos de la función de recepción de Bitcoin de nuestra billetera. Ahora, comenzaremos a implementar la observación de nuevos bloques que se agreguen a la blockchain para que podamos actualizar el número de conformaciones que son direcciones que tienen C, sí. 37. 35 Recepción de bloque parte 1 skillshare 2: En este video, realizaremos pruebas para asegurar que cuando se extrae un bloque en la Blockchain, nuestra billetera reciba transacciones actualizadas con conformaciones crecientes. Entonces movamos los métodos auxiliares en la clase de prueba Bitcoin de recibo a la prueba GUI para que podamos usar estos métodos en otras clases que la extiendan. Ahora, movamos todas estas propiedades a la clase GUI también por la misma razón. Ahora, vamos a cortar estas dos líneas y pegarlas a la cartera de carga y agregar método balanceado en la clase de prueba GUI. En el método de configuración en la clase de prueba recibida, simplemente llamaremos a este método. Eliminemos todas estas importaciones no utilizadas en esta clase. En la clase de prueba GUI, vamos a hacer estos métodos y propiedades protegidos. Ahora en el paquete de prueba GUI, vamos a crear la clase de prueba de bloque de recepción. Extenderá la clase de prueba GUI. Vamos a copiar el método de configuración y la prueba de Bitcoin de recepción y pegarla aquí. También copiemos la primera prueba en la prueba de recibir Bitcoin y pegarla en la clase de prueba de bloque receptor. Se utilizará como plano para la próxima prueba que creemos. Cambiemos el nombre de la billetera creada a mi billetera de prueba cinco. Vamos a cambiar el nombre del tubo de ensayo debe recibir Bitcoin y agregar confirmaciones de hashtag, confirmaciones para recibir ese vestido. Las conformaciones de hashtag serán interpoladas por la variable de prueba de confirmaciones que crearemos. Ahora, después de enviar Bitcoins llamará al método de bloques de minas, pasando como parámetro la variable de confirmaciones. Vamos a crear este método. Tomará un int como su parámetro. Este método usaremos el nodo generar para dirigir al cliente a los bloques de mina. Así que vamos a pegar un poco de código en él. En la clase de prueba GUI, copie esta línea de código y peguela aquí. Modificar el nombre de la variable de dirección para anotar la dirección. Haz lo mismo con esta otra línea. Cambiar el segundo parámetro del método de generación a bloques. Por lo que utilizará esta variable para definir el número de bloques que va a minar y cambiar este parámetro para anotar dirección. Ahora, vamos a copiar este peso para una llamada de método y pegamos aquí. Eliminar estas partes del código. Este método esperará hasta que el primer valor de celda de confirmación de fila de la tabla de direcciones sea igual a la variable blocks. En el bloque Venn comprobará si el valor de celda de confirmación de la primera fila de tabla es igual a la variable de confirmaciones. Incluyamos una cláusula where. Aquí. Vamos a establecer la confirmación es variable para algunos valores de prueba. Añadiremos un marcador de posición para la segunda columna en el WhereClause, porque aparentemente solo funciona cuando tiene dos o más columnas. Vamos a establecer los valores de las confirmaciones en 12.3. Ahora, ejecutemos nuestro nodo Bitcoin, y hagamos nuestra nueva prueba. Genial, las pruebas han pasado. Ahora, hagamos otra prueba para el siguiente escenario. Queremos saber qué sucede cuando una dirección recibe dos transacciones. Y la segunda transacción tiene menos conformaciones que la primera. En este caso, esperamos que el número de dirección de conformaciones sea igual al número de conformaciones de la transacción con menos conformaciones a esa dirección. Así que vamos a duplicar la primera prueba. Cambiemos su nombre a debería recibir Bitcoin y considerar la transacción con menos conformaciones como las confirmaciones de dirección. Cambiemos el nombre de crear billetera a mi billetera de prueba seis. Ahora, vamos a duplicar estas líneas de código para enviar bitcoins y minar bloques de nuevo. En la segunda llamada de bloques mineros sumar menos uno en su parámetro para minar menos bloques después de la segunda transacción. En el bloque, esperamos confirmaciones menos uno como el número de confirmaciones en la primera fila de la tabla. Eliminemos esta línea ya que no queremos este caso de prueba porque intentaría pensar en cero bloques en la segunda llamada de bloques de mina, lo que fallaría. Realicemos nuestras pruebas de nuevo. Genial, las pruebas han pasado. Por lo que concluimos que nuestra cartera ya está preparada para actualizar el número de conformaciones de nuestras direcciones. Eso es porque después de cada bloque de mina, el nodo envía un mensaje a través de cero MQ a nuestra aplicación que contiene las transacciones previamente importadas, pero con un número actualizado de confirmaciones. 38. 36 Recepción de la transacción parte 1 skillshare 2: En este video, comenzaremos a hacer la tabla de transacciones. Esta tabla será similar a la tabla de direcciones, pero en lugar de filas que contengan información sobre direcciones, esta tabla contendrá información sobre cada transacción que envíe o reciba nuestra billetera. Entonces comencemos a crear una prueba GUI para esta tabla. En el paquete GUI, cree una clase llamada prueba de transacción de recepción. Copie estos métodos de la prueba del bloque receptor y péguelos aquí. Esta clase extenderá la clase de prueba GUI. Cambiar este nombre de prueba para tener debe recibir la transacción. Vamos a formatear este método. Quitar es donde bloquear, cambiar el nombre de crear billetera a mi prueba mientras sea siete. Suprimir esta línea. Ahora, después de llamar al método sleep, hagamos que la prueba haga clic en un componente con una pestaña de identificación ética de transacciones. Ahora, agreguemos otro parámetro opcional al método send Bitcoin and wait. Este parámetro será una cadena y se llamará componente de búsqueda. Su valor predeterminado será la tabla de direcciones de hashtag. Sustituyamos este parámetro en la llamada al método de búsqueda por la variable de componente de búsqueda. Ahora en la prueba, agreguemos estos parámetros al método send Bitcoin and wait. El cuarto parámetro será la tabla de transacciones de hashtag. De esa manera después de enviar una transacción, esta llamada al método esperará a que la tabla de transacciones se complete con una fila que contenga un saldo de 1.0 Bitcoin. Ahora, cambiemos el parámetro del método de búsqueda a la tabla de transacciones de hashtag, también. En el bloque de entonces, vamos a dejar la aserción del tamaño de fila de la tabla siendo igual a uno por ahora. Ahora, diseñemos nuestra mesa. Vayamos al patio de recreo punto FXML. Vamos a copiar todo este contenido entre la etiqueta de tabulación y pegarlo a continuación. Ahora cambia su propiedad de texto a transacciones y su ID de ética a pestaña de transacciones. También cambie el identificador de ética de la etiqueta de vista de tabla a la tabla de transacciones. Ahora cambiemos el campo de texto de la primera columna a ID de transacción. La tabla también tendrá una columna balanceada y una columna de confirmaciones. Por lo que vamos a mantener estas etiquetas tal como están. Duplicemos la última etiqueta, cambiemos su texto a la fecha. Esta columna contendrá la fecha de creación de estas transacciones. Ahora hagamos clic en el Scene Builder para ver cómo se ve nuestra nueva pestaña y tabla. Bien, se ve bien. Ahora, vamos a crear un nuevo FXML para este componente. Llamémoslo tabla de subrayado de transacciones. Eliminemos el código estándar. Vamos a copiar este contenido desde el punto de juegos FXML y pegarlo aquí. Vamos a importar estas etiquetas. Cambia esta etiqueta a fx colon route. Eliminar este contenido como su tipo. Vamos a establecer la ruta del componente de vista de tabla y establecer esta URL como el campo XML NS como la tabla de transacciones de conjunto de propiedades de ID de ética. Ahora borra estas etiquetas, que no necesitábamos copiar. Ahora agreguemos estas identificaciones de ética a estas etiquetas de columna. Serán útiles más adelante cuando hagamos el controlador de la tabla de transacciones. Ahora en la ventana principal punto FXML, vamos a duplicar el contenido entre estas etiquetas. Cambiemos el texto de la pestaña a transacciones y es FX ID a pestaña de transacciones. Ahora, cambie esta etiqueta a controlador de tabla de transacciones. Vamos a crear este controlador en el paquete de controladores de puntos GUI. Vamos a importar a la ventana principal punto FXML. Ahora agreguemos la anotación de componente al controlador de la tabla de transacciones. Extenderá la clase de vista de tabla parametrizada con la clase de fila de transacción que crearemos. Vamos a crear la clase real de transacción en el paquete observables. Ahora, vayamos al controlador de pestañas Recibir y copiar su constructor y pegarlo aquí, realizando las modificaciones correspondientes al mismo. Cambiemos su anotación de valor para que apunte al punto de tabla de subrayado de transacciones FXML. Inyectemos también la cartera actual en esta clase. Será útil más adelante. Ahora, necesitamos incluir el controlador de tabla de transacciones en la lista de componentes personalizados en el listener iniciado GUI, simplemente podríamos agregar otra o cláusula en la sentencia if en la inicialización Método FXML. Pero vamos a refactorizar esta clase haciendo lo siguiente. Vamos a crear un conjunto estático privado de objetos de clase llamados componentes personalizados aquí. Vamos a instanciarlo aquí con la clase set de método. Incluyamos estas clases de controlador en el conjunto. Ahora en la sentencia if solo verificaremos si el conjunto de componentes personalizados contiene el tipo dado. Ahora vayamos a la prueba de transacción receptora. Ahora, ejecutemos los objetivos de Maven del ciclo de vida limpio y compilado. En ocasiones esto es necesario para incluir nuevos archivos FXML en el proyecto compilado. Ahora, ejecutemos nuestro nodo central de Bitcoin si aún no se está ejecutando. Por último, hagamos la prueba. La prueba ha fallado porque no ha encontrado una fila que contenga la información de transacción en la tabla de transacciones, continuará implementando esta función en el siguiente video. Nos vemos. 39. 37 Recepción de la transacción parte 2 skillshare: En este video, terminaremos la implementación de la tabla de transacciones y haremos que esta prueba pase. Entonces vamos al servicio de actualización UTXO. Si recuerdas, este método de actualización se llama después de recibir una transacción de nuestro nodo, la clase de tarea nodo monitorea nuestro nodo en busca de mensajes de transacción. Entonces nuestra aplicación publica un evento de transacción recibida que es escuchado por nuestro oyente de transacciones. El oyente de transacciones analiza y filtra el mensaje y llama al método de actualización del servicio UTXO de actualización. Entonces, después de recuperar UTXOS y actualizar las direcciones actuales de la billetera, actualicemos las transacciones actuales de billetera usando este servicio. Vamos a inyectarlo en esta clase. Vamos a crearlo en el paquete de servicios punto GUI. Vamos a agregarle la anotación de servicio. Ahora, terminemos de inyectarlo en esta clase. Ahora, llamemos al método update en este servicio, pasando como parámetro la variable UTXOS. Vamos a crear este método. Este método se ejecutará de forma asíncrona. Así que vamos a agregarle la anotación asíncrona usando el servicio ejecutor predeterminado como su parámetro. Hagamos lo mismo con el método update en el servicio update current wallet addresses. Ahora vamos a implementar el método de actualización y el servicio de transacciones Wallet actual de actualización convertirá la lista de UTXOS en una lista de filas de transacciones y almacenará el resultado en las filas de transacciones el siguiente código filtrará el flujo de UTXOS manteniendo en el flujo solo los UTXOS con direcciones en la billetera actual. Entonces, vamos a inyectar la cartera actual en esta clase. Ahora, en el cuerpo lambda obtendrá todas las direcciones como cadenas y verificará si contiene la dirección UTXO. Ahora, llamaremos al método map en la secuencia resultante, pasando la fila de transacción del método como su parámetro. Vamos a crear este método. Será un método estático y devolverá un objeto de fila de transacción. Similar a la clase de fila de direcciones. La clase de fila de transacción representará una fila y la tabla de transacciones. Así que agreguemos las siguientes propiedades a esta clase. Cada propiedad representará una columna en la tabla de transacciones. Eliminemos la palabra clave final de cada propiedad porque el IDE lo hace permite crear automáticamente setters para estas propiedades si su final. Ahora usando esta función de ID, agregue getters y setters para cada propiedad. Ahora podemos volver a agregar la palabra clave final a estas propiedades. Ahora, vamos a crear un constructor. El constructor tomará cada propiedad de clase como sus parámetros. Y usaremos los setters de propiedades para establecer las propiedades en el cuerpo del constructor. Ahora, podemos seguir implementando el método. Devolverá una nueva fila de transacciones con los siguientes parámetros. Volver al servicio de transacciones Update Current Wallet. Ahora vamos a convertir la cadena resultante en una lista. Ahora agregaremos la rosa de transacción obtenida a la billetera actual usando el método add transactions rows. Vamos a crear este método. Utilizará el campo de filas de transacciones. Así que vamos a crearlo ahora. Es tipo serán las transacciones Rose Class. Vamos a crearlo en el paquete observables. Volver a la cartera actual. Hagámoslo definitivo e instanciémoslo aquí. Hagamos también final el campo de filas de direcciones. En el método ED transactions rows, llamemos al método add transactions rows en el campo de filas de transacción. Pasando las filas de transacción dadas como su parámetro. Vamos a crear este método. Al igual que la clase de filas de direcciones es responsable administrar la lista de filas de direcciones que se muestra en la tabla de direcciones. Esta clase hará lo mismo con las filas de transacciones y la tabla de transacciones. Entonces, para cada fila de transacción, verificaremos si el campo de hoja de ruta de transacciones ya lo contiene. Así que vamos a crear este campo. Será un mapa observable donde la clave es una cadena y el valor es una fila de transacción. Vamos a instanciarlo aquí con un envoltorio de mapa observable, pasando un nuevo HashMap vinculado como su constructor. Entonces, si la hoja de ruta la transacción contiene el ID de fila de transacción en sus claves, entonces estableceremos la rotación de la transacción a la fecha de la transacción presente en la hoja de ruta de transacción que servirá que para preservar la fecha de creación de la transacción. Luego, después de la declaración if, eliminará la fila de transacciones del mapa por su ID y volverá a colocar la fila de transacciones dada en la hoja de ruta de transacciones usando su ID como clave. Nuevamente, estamos eliminando y agregando la misma fila de transacciones para forzar al mapa observable a publicar eventos de cambio que se escucharán más adelante. Ahora, vamos a crear el campo de lista observable que se utilizará para vincular los cambios en la hoja de ruta de transacciones al controlador de tabla. Vamos a instanciarlo aquí usando un envoltorio de lista observable instanciado con una nueva lista enlazada. Ahora vamos a crear el método obtener lista de filas de transacciones observables. Devolverá la lista de roles de transacción. Ahora vinculará la hoja de ruta de transacciones con la lista de roles de transacción en el constructor, tal como hicimos para el conjunto de filas de direcciones y la lista de filas de direcciones en la clase de filas de direcciones. Entonces, para acelerar las cosas, copiemos el constructor de filas de direcciones y péguelo aquí. Arreglemos su nombre. Ahora, en lugar de llamar a métodos en la lista de roles de dirección, lo haremos en la lista de roles de transacción. En lugar de usar un listener set change usará un listener de cambio de mapa parametrizado con una cadena y una fila de transacción. Además, en lugar de usar el elemento get eliminado aquí, usaremos el getValue removed. Aquí. Usaremos el get value added. Y aquí agregaremos un oyente a la hoja de ruta de transacciones. Una cosa más para que esto funcione, tenemos que implementar el método equals en la clase de fila de transacción. Esto se debe a que la lista de filas de transacciones, usaremos el método para decidir qué fila de transacciones eliminar de sí misma. Así que vamos a implementarlo usando esta función IDE. Asegúrese de marcar la casilla de verificación use getters en esta ventana utilizará solo la propiedad ID para definir la igualdad en esta clase. Además, da clic en la casilla de verificación ID aquí para que no pueda ser nulo. Bien, el IDE generó estos métodos como se esperaba. Volver a la clase de filas de transacción. Vamos a crear el método clear, que se llamará cuando se cree una nueva billetera. En su interior llamará al método claro en la hoja de ruta de transacciones y en la lista de roles de transacción. En la clase de billetera actual, vamos a crear el método de filas de transacciones observables buenas. Devolverá que obtienen una llamada al método de lista de filas de transacciones observables llamada al método de lista de filas de transacciones en el campo de filas de transacciones. Vamos a crear también el método de transacciones claras aquí. Llamará al método claro de filas de transacción que acabamos de crear. Ahora vamos a la actualización actual del servicio de monedero. Aquí llamaremos al método actual de transacciones de compensación de billetera . Al hacerlo, nos aseguramos de borrar las filas de transacciones después de crear una billetera. Ahora, vayamos al controlador de la tabla de transacciones. Vamos a agregar los siguientes campos. Se utilizará en el método inicializado posteriormente para enlazar la tabla y sus columnas a las filas de transacciones observables. Ahora vamos a crear el método inicializado. Aquí, primero estableceremos elementos de la tabla de transacciones en las filas de transacciones observables de billetera actuales. Ahora agregaremos un oyente a las filas de transacciones observables actuales de la billetera. Llamaremos al método de actualización de la tabla de transacciones en el cuerpo para que cada cambio que ocurra en el observable desencadene un redibujo de la tabla. También vinculará cada campo de columna al campo de fila de transacción usando la fábrica de valores de celda establecida, tal como lo hicimos en el controlador de la tabla de direcciones. Como parámetro de fábrica de valor de propiedad, tenemos que usar los mismos nombres de propiedad que hemos usado en la clase real de transacción para hacer el enlace correctamente. Duplicemos esta línea tres veces y cambiemos las columnas que estamos vinculando. Ahora vayamos a la clase de prueba de transacción receptora. Asegúrate de que estás ejecutando el Bitcoin Core Node y ejecuta la prueba. Boops, la prueba ha fallado. Veamos por qué. Hay un problema con el campo balanceado de transacciones de columna en el controlador de la tabla de transacciones. Para solucionarlo, vamos a ir a la tabla de subrayado de transacciones punto FXML. El problema es que mal nombramos el saldo, las confirmaciones y los ID de FX de fecha. los tres les falta la palabra transacción tras columna. Así que vamos a arreglarlos y volver a ejecutar la prueba. Genial, La prueba ha pasado. En el siguiente video, agregaremos más pruebas para asegurarnos la tabla de transacciones funcione según lo previsto. C, sí. 40. 38 Recepción de la parte 3 de la transacción skillshare: En este video, agregaremos más pruebas para verificar si nuestra tabla de transacciones funciona para otros escenarios. Entonces vayamos a la clase de prueba de bloque receptor. En cada método se agregará código para probar si la tabla de transacciones contiene la información esperada sobre las transacciones receptoras. Entonces, cambiemos el nombre de la vista de tabla en esta prueba para abordar su vista de tabla, para aclarar su significado. Ahora, llamaremos al método click on pasando como su parámetro, las transacciones de cadena. Ahora vamos a copiar la línea con la variable de vista de tabla de direcciones y pegarla a continuación. Cambiemos este nombre de variable a la vista de tabla de transacciones. En el método de búsqueda, sustituyamos este parámetro por la tabla de transacciones de hashtag. Ahora vamos a copiar estas dos líneas y pegarlas a continuación y cambiarlas para llamar a estos métodos en la vista de tabla de transacciones. Hagamos lo mismo con el otro método de prueba. Pero en este caso, esperamos que la tabla de transacciones contenga dos líneas, una por cada transacción. Y para la segunda fila, esperamos que el número de confirmaciones sea igual a la variable de confirmaciones totales, lo que creará el valor total de confirmaciones será igual al número de bloques míos hasta el momento, este número será igual a confirmaciones más confirmaciones menos uno. Como esperamos que la segunda fila contenga información sobre la primera transacción, se confirmará esta cantidad de veces. Hagamos un pequeño arreglo en el método de bloques de minas. A veces esta línea de código genera una NullPointerException debido a TableView tiene una propiedad null items. Para evitar eso, usemos el operador seguro nulo antes de cada propiedad en la vista de tabla. Ahora, hagamos nuestras pruebas. Primero, asegúrate de ejecutar tu nodo Bitcoin. Vamos a hacer las pruebas. Las dos últimas pruebas han fallado. Eso pasó porque las transacciones en la tabla, estamos desordenadas, su orden es aparentemente aleatorio. En ocasiones estas pruebas pueden pasar porque se pueden ordenar correctamente por casualidad. Entonces arreglemos eso. Nuestro objetivo es ordenar las transacciones por fecha con las transacciones más recientes en las primeras filas. Entonces vayamos a la clase de fila de transacciones. En el método from. Cambiemos la forma en que pasamos los datos a la instanciación de la fila de transacciones. En lugar de usar una nueva fecha, usemos el método instant now. Estamos haciendo eso porque la clase instantánea es más precisa y más fácil de ordenar Parson. Ahora vamos al controlador de la tabla de transacciones. En la tabla de transacciones establecer artículos método de llamada. Pasemos una nueva lista ordenada como parámetro. Las filas actuales de transacciones observables de monedero serán el primer parámetro que instancie la lista ordenada. El segundo parámetro será el comparador que compara la llamada al método. Este método pasará una lambda como primer parámetro o una fila de transacción será el parámetro en el cuerpo lambda. Llamemos al método de análisis instantáneo, pasando la transacción rotate como su parámetro. El método parse generará un objeto de instancia a partir de la cadena de fecha. El segundo parámetro del método de comparación será la llamada al método de orden inverso del comparador. De esta manera, esperamos que la tabla de transacciones se ordene primero por la fecha de transacción con las últimas transacciones. Ahora volvamos a hacer nuestras pruebas. Esta vez sólo los que han fallado. Lo haremos haciendo clic en este botón. Genial, las pruebas han pasado. Ahora agreguemos las pruebas de tabla de transacciones a la clase de prueba de Bitcoin de recepción. Haremos lo mismo que hicimos en la clase de prueba de bloque receptor. Para cada método, refaccionaremos el nombre de la vista de tabla, haremos que la prueba haga clic en la pestaña de transacciones y haremos aserciones sobre el contenido esperado en la tabla de transacciones. Vamos a hacerlo. Bien, ahora, hagamos estas pruebas. Genial, las pruebas han pasado. Ahora ejecutaremos nuestra billetera en el entorno de red de prueba por primera vez. El entorno de la red de prueba es similar al de la red principal, pero sus monedas carecen de valor. Es mucho más fácil de pensar y su tiempo de bloqueo es más corto. Requiere que ejecutemos y hundamos nuestro nodo Bitcoin en este entorno. Cubrimos cómo hacerlo en la guía de configuración del curso. Entonces, modifiquemos nuestro bitcoin.com para ejecutar nuestro nodo en el entorno de red de prueba. Simplemente cambie esta clave de reg test a test net. Dejemos de ejecutar nuestro nodo en la prueba reg. Y volvamos a ejecutar nuestra nota para comenzar a hundir nuestra nota en la red de prueba. Mi nota casi se hunde, así que tardará unos minutos en ponerse al día. Pero dependiendo de la última vez que lo ejecutaste, puede que nos lleve más tiempo sincronizar porque nos llevará algún tiempo descargar los últimos bloques. De todos modos, mientras se está hundiendo, modifiquemos nuestros proyectos para que podamos ejecutar nuestra aplicación en la red de pruebas con éxito. En la ruta de recursos, vamos a crear las propiedades de punto neto de prueba de aplicación de archivo . Este archivo contendrá las propiedades utilizadas en nuestro proyecto cuando ejecutemos la aplicación en el entorno de red de prueba. Vamos a copiar el contenido del archivo de propiedades del punto de la aplicación propiedades del punto de la aplicación y pegarlo aquí. Ahora, cambie el entorno de Bitcoin para probar net. Y el puerto URI punto RPC no dot 218332. Este es el puerto predeterminado de nuestro nodo cuando se ejecuta en el entorno de red de prueba. Ahora, hagamos una pequeña mejora. En nuestro monedero, Sería bueno poder copiar el ID de transacción que se muestra en la tabla de transacciones simplemente haciendo clic derecho sobre ellas y haciendo clic en Copiar. Implementemos esta característica. Para ello, vayamos a la tabla de subrayado de transacciones punto FXML. Ahora agreguemos aquí el siguiente código. Primero, agreguemos estas etiquetas de menú contextual dentro de él. Agreguemos la etiqueta items. Después la etiqueta de los elementos del menú. En esta propiedad de texto etiquetas agregue la copia de cadena y identificador de transacción de café hashtag ya que está en la propiedad de acción. Esto le dice a la aplicación que llame al método Copy Transaction ID en el controlador de la tabla de transacciones. Después hacemos clic en el elemento Copiar menú en el menú contextual. El menú contextual es un menú que aparece después de que hacemos clic derecho en algo en la pantalla. Ahora, vayamos al controlador de la tabla de transacciones. Vamos a crear el método de copia ID de transacción aquí. Primero, obtendremos la fila de transacciones en la que se hizo clic con el botón derecho usando este código. Ahora simplemente llamaremos al método copy. Crearemos pasar el ID de fila de transacción como su parámetro. Para crear este método se creará primero un paquete utils dentro del paquete BYOD W. En su interior, vamos a crear una clase llamada Copy. Ahora, vamos a crear el método copy aquí. Como método estático. Instanciará un objeto de contenido del portapapeles, almacenándolo en la variable de contenido. Entonces llamaremos al método put string en él, pasando la variable text como su parámetro. Agreguemos esta variable como parámetro del método copy. Finalmente, llamaremos al método del portapapeles del sistema get y estableceremos su contenido el contenido variable en el controlador de la tabla de transacciones. Vamos a importar este método. Una cosa más. Al ejecutar el nodo Bitcoin en el entorno de red de prueba, nuestro nodo puede recibir diferentes tipos de transacciones que la biblioteca Java de Bitcoin aún no puede analizar y generan errores al intentar hacerlo . Aunque no analizar estas transacciones afectará a nuestras billeteras, el error se plantea bien. Para evitar eso, en la clase de tarea de nodo, envuelva el método de transacción del flujo de bytes en un bloque try-catch. En el bloque catch, usemos un registrador para advertirnos del error. En la llamada a un método pasará una frase que indica el error y un par de llaves al final. Estas llaves serán interpoladas por el segundo argumento, que será la variable de contenido codificada hexadecimal. El tercer parámetro será el objeto de excepción. Así podemos acceder a toda la traza de pila del error en los registros. Después del registro, el error irá directamente a la siguiente iteración del bucle while usando la palabra clave continue. Vamos a crear el campo logger. Será una propiedad estática. Vamos a instanciarlo aquí usando la fábrica de registradores. Arreglemos la importación de la clase logger. En realidad, tenemos que importarlo del paquete 4D dot SELF for J. Ahora vamos a ejecutar nuestra aplicación en el entorno de red de prueba. Primero, comprobemos si nuestro nodo está vinculado en el entorno de red de prueba. Bien, ya se hunde porque es progreso es igual a 1.00. Ahora vamos a la clase de aplicación BYOD W. Haga clic con el botón derecho en este símbolo y haga clic en modificar Configuraciones de Ejecución. Ahora, haga clic en modificar opciones y asegúrese de que las opciones de VM del anuncio estén seleccionadas. Ahora conéctelo a menos d perfiles de puntos de resorte punto activo es igual a red de prueba. Haga clic en Bien y haga clic en el botón Ejecutar. Ahora vamos a crear una cartera. Observe que la dirección de recepción comienza con TB, indicando que es una dirección neta de prueba. Ahora, copiemos esta dirección. Utilizará un grifo de red de prueba para obtener Bitcoins netos de prueba. Un grifo de Bitcoin es un sitio web o API que ofrece Bitcoins de forma gratuita. Fueron muy populares en los primeros años de Bitcoin, cuando uno Bitcoin era muy barato. Hoy en día, hay forma rápida de obtener monedas netas de prueba. Vayamos al sitio web en la pantalla. Es un grifo de red de prueba. Pegemos la dirección copiada en este campo. Elija una cantidad, y haga clic en este botón para enviarnos Bitcoin. Esperemos un poco. Bien, la alerta dice que envía algunos Satoshi's a nuestra cartera. Comprobemos si lo hemos recibido. Genial. Nuestra billetera identificó nuestra transacción y nuestra transacción y dirección ya tienen una conformación. hay una cosa rara. El saldo está formateado en notación científica. Lo arreglaremos más tarde. Por ahora, copiemos nuestro ID de transacción haciendo clic derecho sobre él y haciendo clic en Copiar. Verificaremos la transacción en un explorador de blockchain de terceros. Un explorador de blockchain es un sitio web que muestra información sobre direcciones, bloques y transacciones de Bitcoin de una manera agradable y organizada. Si le preocupa su privacidad, buscar sus vestidos rojos y transacciones en el no es recomendable buscar sus vestidos rojos y transacciones en el explorador blockchain de terceros ya que les permite vincularlo con los datos de su billetera. Pero como solo lo estamos usando para fines de prueba, está bien. Dicho esto, vayamos al sitio web en la pantalla, que es un explorador blockchain net de prueba de Bitcoin, peguemos el ID de transacción copiado en el campo de búsqueda y hagamos clic en el botón Buscar. Aquí, obtendremos alguna información sobre nuestra transacción. Observe que ya tiene dos confirmaciones, pero nuestro monedero indica que solo tiene una conformación. Resulta que en el entorno de red de prueba, nuestro nodo Bitcoin solo envía notificaciones de transacciones a través cero MQ cuando se envían las transacciones y cuando reciben una confirmación. Después de eso, no importa cuántas confirmaciones más obtengan, el nodo no notifica a nuestra aplicación al respecto. Tenemos que hacer que nuestra aplicación comience a escuchar notificaciones de bloqueo para que podamos solucionar este problema. Empezaremos a hacer esto en el siguiente video. Nos vemos. 41. 39 Recibir bloque parte 2 skillshare 2: En este video, haremos que nuestra aplicación comience a escuchar mensajes de bloqueo del nodo Bitcoin. De esa manera, podremos actualizar nuestras confirmaciones de transacciones correctamente en el entorno de red de prueba. También modificará el formato de direcciones y saldos de transacciones, ya que ahora no se están mostrando muy bien en las tablas. Entonces vamos al archivo bitcoin.com. Cambiemos esta clave para reg test. Para comenzar a escuchar mensajes de bloque, agreguemos aquí la propiedad Z MQ pub hash block. Su valor será la misma URL en la propiedad anterior. Así que vamos a pegarlo aquí. Esta configuración hará que los nodos envíen el bloque hash a nuestra aplicación después de que detecte un nuevo bloque, extendiendo la cadena de bloques. Después de eso, el código creará, enviará una lista de solicitud no gastada al nodo que contiene todas las direcciones actuales de billetera. En respuesta recibirá una lista de UTXOS actualizados que analizarán y usarán para actualizar nuestros vestidos rojos y tablas de transacciones. Guardemos el archivo bitcoin.com. Ahora, vayamos a la clase de tareas de nodo. Duplicemos esta línea. Cambiemos la cadena a bloque hash. De esa manera, comenzaremos a recibir mensajes de bloque hash desde el nodo. Ahora, en esta declaración if, agreguemos el siguiente código. Si el tema es igual nulo, o la lista con estos temas no contiene el tema recibido. Después iremos a la siguiente iteración del bucle while. Ahora, agreguemos aquí una declaración switch. En caso de que la variable topic sea igual a ra t x Luego ejecutamos el código para analizarlo y procesar la transacción recibida. Movamos a esta ubicación la línea que publica el evento de transacción recibida. De esa manera podremos eliminar esta sentencia redundante continue en caso de que la variable topic sea igual al bloque hash. Luego usaremos el editor de eventos de la aplicación para publicar un nuevo evento recibido por bloques. Vamos a crear este evento en el paquete BYU w dot sin duda eventos. Ahora vamos a crear un oyente para este evento en el paquete BYOD w dot, dot listeners. Vamos a agregarle una anotación de componente. Hagamos que implemente la interfaz de escucha de aplicaciones, pasando el evento block received como su parámetro type. Implementemos su método. Primero. Obtendremos todas las direcciones actuales de billetera usando este método y las almacenaremos en la variable direcciones. Inyectemos la cartera actual en esta clase. Entonces usando una sentencia if comprobará si la variable addresses está vacía. Si no lo es, entonces usaremos el servicio de actualización UTXOS para actualizar nuestras direcciones y transacciones. Vamos a inyectarlo en esta clase. Llamaremos al método de actualización en él, pasando la dirección es variable y el nombre de la billetera actual como sus parámetros. Ahora vamos a ir a la transacción recibida oyente va a optimizar nuestro código. Recuerde que después de recibir una confirmación en el entorno de red de prueba y todas las confirmaciones en el entorno de prueba reg, el nodo envía un mensaje de transacción a nuestra aplicación a través de cero MQ. Dado que a partir de ahora nuestro oyente recibido en bloque actualizará todas las direcciones actuales de billetera cuando reciba confirmaciones, no tiene sentido actualizar la tabla de direcciones y transacciones en la transacción recibió clase de oyente después de recibir mensajes de transacción repetidos más. Por lo tanto, modificaremos esta clase para procesar únicamente transacciones si la cartera actual no las contiene. Entonces agreguemos esta declaración if. Si los ID de transacción actuales de Wallet contienen el ID de transacción recibida, entonces simplemente regresamos. Vamos a crear este método. Devolverá una lista de cadenas, y devolverá las filas de transacción, obtendrá el método de ID de transacción. Vamos a crear este método. Aquí. Devolveremos el siguiente código de una secuencia de la lista de roles de transacción. Llamaremos al método map pasando una referencia al método getID de fila de transacción. Luego convertiremos el resultado a una lista y lo devolveremos al oyente de transacción recibida. Tenemos que envolver este código en un bloque try catch porque el método de ID de transacción arroja una excepción marcada en el bloque catch, utilizará un registrador para imprimir un mensaje de advertencia. Inyectemos el registrador en esta clase, tal como lo hicimos en la clase de tareas de nodo. También agreguemos una declaración return al bloque catch. Ahora, solucionemos el problema de formato equilibrado de fila de direcciones. En lugar de usar el método de cadena de dos clases dobles, usaremos el método de formato o formato Bitcoin pasando el saldo de direcciones como su parámetro. Vamos a crear esta clase en el paquete utils. Ahora, vamos a crear el método format. Aquí, instanciaremos un nuevo objeto de símbolos de formato decimal pasando la ruta regional a su constructor. Luego estableceremos el punto como su separador decimal y la coma como separador de agrupamiento. Entonces instanciaremos un nuevo objeto de formato decimal ya que su parámetro constructor pasará este patrón. Y la variable de símbolos. Después estableceremos el formato o agrupación utilizado como false. Entonces estableceremos sus dígitos mínimos de fracción en ocho. Y es la fracción máxima de dígitos 282. Finalmente, llamaremos al método format en el formateador, pasando el número recibido como parámetro y lo devolveremos. Mediante este método formateará cualquier número de pase a él con dígitos decimales y sin separadores de agrupación. Este tipo de formato es útil ya que un bitcoin puede tener como máximo ocho dígitos de fracción. Este formato también facilita la visualización de cuántos Satoshi es un contenido equilibrado. Ahora vamos a la clase de fila de transacciones. Vamos a usar el formateador Bitcoin aquí para, para formatear el saldo UTXO en el método frame. Ahora, ajustemos nuestras pruebas para cubrir este nuevo formato de saldo. Vamos a la clase de prueba GUI en el método send Bitcoin in weight, cambiemos el segundo tipo de parámetro a double y ajustemos su valor predeterminado en consecuencia. También agreguemos este parámetro de cantidad opcional con un valor predeterminado de 1.0. Ahora, sustituyamos este parámetro por la variable amount. Y aquí vamos a envolver la variable de cantidad total esperada en el formato Bitcoin o método de formato. Ahora, vayamos a la prueba de recibir Bitcoin. Modifiquemos esto y Bitcoin y espere al método de llamada para enviar 0.00 001 Bitcoin. Para que podamos probar el nuevo formato cuando nuestro monedero reciba fracciones de Bitcoin. Ahora, comprobemos cada uso de este método y modifiquemos su parametrización del parámetro de cantidad total esperada para pasar un doble en lugar de una cadena. Ahora, agreguemos estas comprobaciones nulas a las propiedades de vista de tabla en este método para evitar tener excepciones de puntero nulo. Ahora, vamos a ejecutar nuestro nodo, y vamos a ejecutar todas las pruebas del proyecto. Genial, las pruebas han pasado. Ahora, ejecutemos nuestra aplicación en el entorno de red de prueba. Para ello, ajustemos nuestro archivo bitcoin.com. Ahora, reiniciemos nuestro nodo. Después de algunos minutos, mi nota está completamente hundida. Ahora, ejecutemos nuestra aplicación en el entorno de red de prueba usando nuestra configuración de ejecución previamente modificada. Vamos a crear una nueva cartera. Ahora, copiemos nuestra dirección y utilicemos un grifo de red de prueba para recibir Satoshi's, tal como hicimos en un video anterior. Bien, nuestras billeteras identificaron con éxito la transacción y está equilibrada es tal como esperábamos. Ahora, comamos un sándwich y dejemos nuestra cartera funcionando por un tiempo. Después de algunos minutos son atendidos y transacción ya obtuvo cuatro confirmaciones. Genial. 42. 40 Saldo total parte 1 skillshare 2: En este video, comenzaremos a desarrollar la función de saldo total. Básicamente, será un texto encima la pestaña de transacciones y direcciones que indica que el saldo de la billetera actualmente cargada mostrará el saldo confirmado, el saldo no confirmado y el saldo total. El saldo confirmado mostrará la suma del monto de todos los UTXOS confirmados. El saldo no confirmado es la suma de todos los UTXO no confirmados. El saldo total será la suma de saldos no confirmados y confirmados. Así que vamos al patio de recreo punto FXML para bosquejar algo. Después del primer panel de pestañas de cierre. Agreguemos esta etiqueta de etiqueta. Ahora, agreguemos esta etiqueta de margen de punto VBox. En su interior. Agrega esta etiqueta de insertos. Vamos a añadir algunas propiedades de margen aquí. Vamos a establecer el margen inferior en 10.0, el margen izquierdo en 10.0 y el margen superior en cero. Ahora, para propósitos de prueba, establecemos la propiedad text de esta etiqueta a esto como una prueba. Veamos cómo se ve en el Scene Builder. Bien, vemos que aquí se ubicarán los textos equilibrados. Eliminemos esta propiedad de texto. Vamos a crear un nuevo archivo FXML llamado saldo de subrayado total. Vamos a quitar este calderero. Ahora, copiemos todo el contenido y la etiqueta de etiqueta que acabamos de crear en el patio de recreo. Y pégalo aquí. También vamos a copiar estas líneas de importación dos y pegarlas en el punto equilibrado de subrayado total FXML. Ahora sustituyamos las etiquetas de etiqueta por la etiqueta de raíz de colon FX. Tendrá un ID FX de balance total y un tipo de Java FX dot, dot control dot label. Incluyamos también esta propiedad XML y S. Ahora en la ventana principal, agreguemos la etiqueta del controlador de saldo total después del primer panel de pestañas de cierre. Ahora vamos a crear este controlador en el paquete de controladores. Y vamos a importarlo aquí de nuevo al controlador. Hagamos que extienda la clase de etiqueta y le agreguemos la anotación de componente. Ahora, vamos a copiar este constructor y pegarlo aquí, modificándolo en consecuencia. El valor del recurso FXML será la ubicación del punto equilibrado de subrayado total FXML. Inyectemos también la cartera actual en esta clase. Ahora en la GUI comenzó el oyente, agreguemos la clase de controlador de saldo total al conjunto de componentes personalizados. En el controlador de saldo total. Vamos a agregar el método inicializado. Usaremos el método setText heredado para establecer el texto de la etiqueta dinámicamente. Vamos a configurarlo para que se pruebe con fines de prueba por ahora. Ahora, vamos a crear la prueba de saldo total en el paquete GUI. Extenderá la clase de prueba GUI. Vamos a copiar estos dos métodos y pegarlos en la nueva prueba. Vamos a cambiar el nombre de este método dos deben calcular el saldo total. Ahora, hagamos algunos ajustes en el cuerpo. El nombre de la cartera creada será mi prueba validar. Eliminemos esta línea ya que no la vamos a necesitar. También eliminemos estas líneas. Con este código, obtendrá el texto presente en la etiqueta de saldo total y lo almacenará en la variable de texto de etiqueta. Entonces block comprobará si la variable de texto label es igual a la siguiente frase. Después de recibir la transacción, esperamos que el contenido de la etiqueta muestre que nuestros saldos totales y no confirmados son un Bitcoin. Esperamos que el saldo confirmado sea cero ya que nuestra transacción no se incluirá en un bloqueo y mente durante la prueba. Antes de ejecutar nuestro nodo, asegurémonos de que nuestro entorno Bitcoin dot conf esté configurado para reg test. Ahora, vamos a ejecutar nuestro nodo. Y hagamos esta prueba. Ha fallado como se esperaba porque la etiqueta de saldo total contiene la prueba de cadena en lugar de lo que queríamos. En el siguiente video, implementaremos esta función y haremos que esta prueba pase. Nos vemos. 43. 41 Saldo total parte 2 skillshare 2: En este video, terminaremos implementar la función de saldo total. Así que vayamos al servicio de actualización UTXOS. En el método de actualización se agregará una nueva llamada a método para actualizar el saldo de la billetera. Para eso, llamaremos al método de actualización en la actualización que creará el servicio de saldo de billetera actual. Inyectemos este servicio en esta clase. Vamos a crear esta clase en el paquete de servicios punto GUI. Y terminemos de inyectarlo aquí. Ahora, vamos a crear su método de actualización. Aquí, primero calcularemos el saldo no confirmado y lo almacenaremos en la variable de saldo no confirmado. Para eso, necesitaremos inyectar la billetera actual en esta clase. Entonces obtendremos sus filas de transacciones observables y las convertiremos en un stream. Luego usaremos el método de filtro en el resultado para excluir las filas de transacciones con confirmaciones diferentes a cero. Luego usaremos el método map para convertir el flujo obtenido en un flujo de saldos de filas de transacciones. Usaremos el método parse double para convertir cada cadena balanceada en una doble. Ahora usaremos el método reducido, pasándole el método de suma doble, a algunos cada saldo obtenido en la corriente. Finalmente, usaremos el método or else pasándole 0.0. Por lo tanto, en caso de que el flujo obtenido esté vacío, la variable balanceada no confirmada se establecerá en cero. Ahora, vamos a duplicar este bloque de código. Vamos a modificarlo para calcular el saldo confirmado y almacenarlo en la variable equilibrada confirmada. Sólo tenemos que cambiar el signo igual y el método de filtro a este signo mayor que. Con esta simple modificación, obtendremos la suma de los saldos de todas las transacciones con al menos una conformación. Finalmente, llamaremos al método de saldos establecidos en la billetera actual, pasando el saldo no confirmado y el saldo confirmado como sus parámetros. Dado que este código modificará la interfaz de usuario, vamos a envolverlo en una plataforma ejecutar más tarde llamada al método. Y vamos a crear el método set balances en la clase actual de wallet. Para ello, agreguemos el campo de saldos a esta clase. Su tipo será la clase de saldos que crearemos. Vamos a crearlo en el paquete observables. Y vamos a instanciarlo aquí. Aquí llamaremos a este método de saldos establecidos en el campo de saldos, pasando los saldos no confirmados, no confirmados como sus parámetros. Vamos a crear este método. Primero. Agreguemos algunos campos privados a esta clase. Añadiremos el campo balanceado no confirmado de la propiedad type string. Vamos a instanciarlo aquí con una nueva propiedad de cadena simple. Duplicemos esta línea dos veces. Cambiemos estos nombres de campo para confirmar el saldo y el saldo total. Ahora en el método set balances llamará al método set en las propiedades inyectadas para establecer sus valores. Utilizará el formato o método de formato Bitcoin para formatear los saldos al formato deseado. Al saldo total pasará la suma de los saldos no confirmados y confirmados. Ahora, vamos a crear getters para estos campos. Creemos también el método claro. Este método establecerá cada saldo de propiedad en cero. Llamaremos a este método después de crear una billetera para borrar los valores de la billetera previamente cargada. Ahora en la cartera actual, vamos a crear el método de los buenos saldos. Devolverá el campo de saldos. Y vamos a crear el método de saldos claros. Llamará al método de compensación de saldos. En el servicio de billetera actual de actualización, que se llama después de que se crea una billetera, llamemos aquí al método actual de saldos claros de billetera. Ahora, vayamos al controlador de saldo total. Vamos a quitar esta línea. Obtendremos la propiedad balanceada no confirmada de los saldos actuales de la billetera. Llamaremos al método del oyente de anuncios en él. Pasaremos una lambda como su parámetro, donde en el cuerpo llamaremos al método update text. Vamos a crear este método. Llamaremos al método SetText en él, y pasaremos una llamada al método de formato de cadena como su parámetro. El primer parámetro del método de formato será esta frase. Cada signo de porcentaje seguido de la letra S será interpolado por los siguientes parámetros de esta llamada al método. Los siguientes parámetros serán el saldo total actual de la cartera. El monedero actual confirmó saldo. Y por último, el saldo actual de la cartera sin confirmar. Ahora en el método inicializado, vamos a duplicar esta línea dos veces. Añadiremos el mismo oyente a la propiedad equilibrada confirmada y a la propiedad de saldo total. Entonces, modifiquemos estas líneas en consecuencia. Vamos a refacturar esta cadena, incluyéndola en una constante en esta clase. Llamémoslo texto equilibrado y hagámoslo privado. Ahora, hagamos una pequeña modificación en el servicio UTXOS de actualización. Observe que ya tenemos una anotación asíncrona en el método de actualización. Entonces agregar la misma anotación en el método se llama un es redundante. Por lo tanto, vamos a eliminarlos. Primero en la actualización actual del servicio de direcciones de monedero. Luego en la actualización actual del servicio de transacciones Wallet. Otra cosa que he notado es que necesitamos envolver la llamada al método de filas de transacción de anuncios y una plataforma aprender más tarde al método de llamada ya que modifica elementos en la interfaz de usuario. Ahora vamos a la prueba de saldo total. Asegurémonos de que nuestro nodo Bitcoin se esté ejecutando. Y vamos a ejecutar nuestros grupos de prueba . La prueba ha fallado. Veamos por qué. Resulta que olvidé agregar la anotación de servicios a la actualización actual del servicio de saldo de billetera. Vamos a arreglar eso. Y volvamos a hacer nuestra prueba. Genial, La prueba ha pasado. En el siguiente video, agregaremos pruebas más equilibradas en nuestras otras pruebas para asegurarnos de que funciona según lo previsto. 44. 42 Saldo total parte 3 skillshare 2: En este video, implementaremos más pruebas para asegurar que la función de saldo funcione correctamente. Entonces copiemos esta línea y la prueba de saldo total, primero agregaremos algunas aserciones de prueba sobre el saldo y la prueba de bloque receptor. Así que vamos a pegar la línea aquí. También copiemos esta línea y la peguemos en el entonces bloque de esta prueba. En esta prueba, esperamos que el saldo total sea igual a un Bitcoin. Entonces, ajustemos esta frase en consecuencia. También esperamos que se confirme todo el saldo. Hagamos lo mismo para esta otra prueba. En este caso, esperamos que el saldo total sea igual a dos bitcoins, también confirmado. Ahora vamos a comprobar si nuestro nodo se está ejecutando y ejecutemos la prueba. Ya pasaron las pruebas. Ahora agreguemos algunas afirmaciones de saldo a la clase de prueba de Bitcoin receptora. En estas pruebas sólo se esperarán saldos no confirmados. Vamos a hacer estas pruebas. Genial, las pruebas han pasado. 45. 43 Enviar bitcoin parte 1 skillshare 2: Bien, hasta el momento con nuestra billetera, podemos recibir Bitcoins usando direcciones generadas. También podemos inspeccionar el saldo recibido por cada dirección y verificar información sobre nuestras transacciones. Ahora, comenzaremos a implementar la capacidad de gastar esos bitcoins enviando transacciones a otras direcciones que queramos. Así que comencemos a crear una prueba llamada send Bitcoin test en el paquete de prueba GUI. Extenderá la clase de prueba GUI. Vamos a añadir el mismo método de configuración. Agregamos otras dos pruebas, llamando a la billetera de carga y agregamos método balanceado. Vamos a crear una prueba llamada debería enviar Bitcoin. Ahora en el bloque eólico, creará una nueva billetera y enviará un Bitcoin a su primera dirección. El siguiente código será muy similar al código de las otras pruebas. Después de enviar un Bitcoin a nuestra dirección de billetera, haremos clic en la pestaña Enviar. Después haremos clic en el campo de cantidad para definir cuánto queremos enviar. Enviemos 0.5 Bitcoin, que es la mitad de nuestro saldo en este punto. Ahora, haremos clic en la dirección para enviar el campo. En esta prueba se enviarán bitcoins a otra dirección. Entonces usemos el Node get new address client para obtener una nueva dirección de nodo. Después escribiremos la dirección obtenida en la entrada clicada. Ahora, haremos clic en el botón Enviar. Después de eso, esperamos que se abra un modal con información sobre la transacción y un botón Ok para confirmar y enviar la transacción. Entonces llamemos al método click on pasando bien, como su parámetro. Ahora haremos clic en la pestaña de transacciones. Y con el siguiente código, verificaremos si la tabla de transacciones tiene dos filas, una para la transacción receptora y otra para la transacción que acabamos de enviar. Ahora, vayamos al punto de juegos FXML para diseñar nuestra pestaña Enviar. Duplicemos el código para la pestaña Recibir. Y cambiemos su texto para enviar. Eliminemos estas líneas así comencemos con una nueva pestaña nueva y fresca en la que trabajar. Ahora, vayamos al Scene Builder. Vamos a hacer clic en la pestaña Enviar. Vamos a hacer clic en el cuerpo de la pestaña para seleccionar el componente del panel de cuadrícula dentro de ella. Vamos a establecer su altura pref a 130, y su ancho pref a 600. Ahora agreguemos un control de etiqueta al panel de cuadrícula dentro de la pestaña Enviar. Pongamos diez a sus márgenes superior, derecho e izquierdo. Cambiemos su nombre para abordar este fin. Ahora, agreguemos un campo de texto a este panel de cuadrícula. Cambiemos su índice de columna del panel de cuadrícula a uno. No nos está permitiendo hacer eso. Primero, tenemos que agregar una columna al panel de cuadrícula. Hagamos clic con el botón derecho aquí y agreguemos dos filas y una columna al panel de cuadrícula. Ahora podemos cambiar el índice de columna TextField a uno. Pongamos diez a sus márgenes superior, derecho e izquierdo. Cambiemos su ancho pref a 350. Cambiemos también este ancho de pref Collins a 600. Agreguemos otra etiqueta al panel de cuadrícula. Cambiemos su índice de fila a uno, y pongamos diez en sus márgenes superior, derecho e izquierdo. Cambiemos también su texto a cantidad a enviar. Agreguemos otro campo de texto al panel de cuadrícula. Y pongamos su índice de fila uno y su índice de columna en uno. Vamos a establecer su altura pref a 26. Y es ancho pref a 100. Pongamos diez a sus márgenes superior, derecho e izquierdo. Ahora envolveremos el último campo de texto insertado en un cuadro H. Entonces agreguemos una caja H al panel de cuadrícula. Y sus índices de fila y columna a uno. Vamos a mover este campo de texto al cuadro H. También pongamos diez a los ocho dólares en los márgenes superior, derecho e izquierdo. Ahora agreguemos una etiqueta a la caja H. También pongamos estos márgenes diez y cambiemos su texto a BTC. En realidad, volvamos a poner estos márgenes a cero. lugar, pondremos cinco a estos paños. Ahora, agreguemos un botón OK al panel de cuadrícula. Y pongamos su índice de filas en dos. También pongamos estos márgenes en diez. Y fijemos su texto para enviar. Ahora, copiemos todo el contenido de la pestaña Enviar que hemos creado en el playground dot FXML. Vamos a crear el envío de subrayado tab dot FXML en el paquete FXML. Y peguemos el contenido copiado en este archivo. Cambiemos la etiqueta de tabulación por la etiqueta de raíz de colon ética. Vamos a establecer su tipo a efectos Java, puntos vistos, control de puntos, pestaña de puntos. Ahora vamos a importar todas las etiquetas restantes. Vaya, establecimos erróneamente la propiedad type a etiquetar. Vamos a arreglarlo. Ahora, vamos a establecer el ID de FX de estas etiquetas. Primero, vamos a establecer este fx ID para enviar tab. Este fx ID a dirección, para enviar este fx ID a cantidad a enviar, este fx ID para enviar. Ahora vamos a ir a la ventana de subrayado principal punto FXML. Duplicemos esta línea y cambiemos esta etiqueta para enviar el controlador de tabulador. Vamos a crear este controlador en el paquete de controladores. Y vamos a importarlo aquí. Extenderá la clase tab y vamos a agregarle la anotación de componente. Vamos a copiar el constructor de la pestaña Recibir y pegarlo aquí, ajustándolo en consecuencia. Inyectemos la cartera actual en esta clase. Ahora agreguemos la clase Send tab controller al conjunto de componentes personalizados en el listener iniciado GUI. Y cambiemos el valor de este parámetro para enviar guion bajo tab dot FXML. Ahora asegurémonos de que nuestro nodo Bitcoin se esté ejecutando. Y vamos a ejecutar nuestra prueba de enviar Bitcoin. Como era de esperar, la prueba ha fallado. En los próximos videos, seguiremos implementando esta función. C, sí. 46. 44 transacciones de Bitcoin parte 2 skillshare: En este video, conoceremos más sobre las transacciones de Bitcoin. Más específicamente, aprenderemos más sobre tamaño de la transacción y las tarifas de transacción. Este conocimiento será necesario más adelante cuando empecemos a construir transacciones para transferir Bitcoins de nuestras billeteras a otras direcciones. De la presentación anterior, aprendimos que la tarifa de transacción es igual a la suma de Bitcoin en entradas menos la suma de Bitcoins y salidas de una transacción. Recuerda que la tarifa de transacción es el precio que pagas para que un menor recoja tu transacción del mental incluido en un bloque y la mine. Cuanto mayor sea la tarifa de transacción, más rápido se incluirá la transacción en un bloque. Con una pequeña tarifa de transacción, su transacción permanecerá en el mental por más tiempo. Por lo tanto, es importante elegir la tarifa correcta para asegurarse de que su transacción se confirme en un tiempo razonable sin pagarla de más. La tarifa de transacción varía mucho con el tiempo. Su valor sigue la lógica de la oferta y la demanda. Cuanto mayor sea el número de transacciones que se envían, mayor tiende a ser la tarifa de transacción. Y cuanto mayor es el número de mineros, menor tiende a ser la tarifa de transacción. Este gráfico muestra la comisión de transacción promedio en dólares en los últimos dos años. Observe que en este periodo, la tarifa de transacción varió de un par de dólares a más de 60 dólares por transacción. Entonces, ¿cómo calculamos la tarifa de transacción? Teniendo en cuenta que los bloques de transacción tienen espacio limitado pero demanda ilimitada, tiene sentido que las tarifas se calculen por tamaño de transacción. Existen diferentes formas de obtener la tasa de comisión de transacción recomendada. Por ejemplo, puede usar sitios web como Bitcoin Fees, earned.com. Aquí podemos ver cuántas transacciones tienen por tasa de comisión en las últimas 24 h. En la columna de la derecha, vemos una estimación de cuánto tiempo tardaría en confirmar una transacción con estas comisiones en bloques y minutos. Si te desplazas hacia abajo, te da una tarifa recomendada para usar. Eso casi garantiza que su transacción será confirmada en el siguiente bloque. Men pull dot space es otro sitio que junto con gráficos geniales, muestran la tasa de tarifa promedio para cada bloque, también muestra la tasa de tarifa recomendada para usar en transacciones de baja, media y alta prioridad. Cuanto mayor sea su prioridad, más rápido se espera que se confirme la transacción. También podemos utilizar nuestro método de tarifa inteligente de estimación de Bitcoin Core Note RPC . Según su documentación, toma como parámetro, un objetivo de confirmación, que es el número de bloques que esperamos realizar transacciones con la tasa de devolución tardará en confirmarse. También se necesita un parámetro opcional para definir el modo de estimación, que puede ser desestablecido, económico o conservador. La tasa de comisión se devuelve en Bitcoin por kilo byte virtual o byte KV. Estos ejemplos muestran que las tarifas recomendadas pueden variar mucho entre diferentes herramientas. Por simplicidad, en nuestra billetera usaremos la llamada RPC de teléfono inteligente de estimaciones Bitcoin Core, ya que no requerirá que consultemos herramientas externas con una tasa de tarifa. Y por lo tanto, podemos calcular la tarifa de transacción multiplicando el tamaño de la transacción en v bytes por la tasa de tarifa en Satoshi es privy bite. Pero espera, ¿qué es un byte virtual? Para calcular las tarifas de transacción, hay dos conceptos importantes a entender primero, tamaño virtual y el byte virtual. El tamaño virtual, o tamaño V, es el tamaño de la transacción en bits virtuales o v bytes. Son conceptos inventados para dar cuenta del menor tamaño de las transacciones Segway. El tamaño V se calcula de una manera compatible con versiones anteriores para que preestablezca qué tamaños de transacción son iguales a preestablecer qué tamaños de transacción V. Para las transacciones Segway, el tamaño V es igual al tamaño de parte no testigo de una transacción más su tamaño testigo dividido por cuatro. El testigo es un campo presente únicamente en transacciones Segway. Contiene los campos que en las transacciones pre segmento se ubicaron en el campo ScriptSig de cada entrada. Esta forma diferente de calcular los tamaños de transacción da como resultado tamaños V de transacción más pequeños para transacciones Segway en comparación con transacciones heredadas. Por ejemplo, para transacciones con una entrada y una salida, las transacciones Segway tienen un tamaño de 110 v bytes, mientras que las transacciones heredadas tienen un tamaño de 192 v bytes. Para transacciones con una entrada y dos salidas, las transacciones Segway tienen un tamaño de 141 v bytes, mientras que las transacciones heredadas tienen un tamaño de 226 v bytes. Finalmente, para transacciones con dos entradas en salidas, las transacciones Segway tienen un tamaño de 209 v bytes, mientras que las transacciones heredadas tienen 374 bytes de tamaño. Entonces digamos que queremos calcular la tarifa para una transacción segue con una entrada y dos salidas con una tasa de comisión de 19. Satoshi es un byte privado. Para ello, multiplicaríamos su tamaño de transacción v, que es de 141 v bytes, por la tasa de comisión, que es de 19 Satoshi por v bytes. Eso daría 2 mil 679 Satoshi en honorarios por esa transacción. Entonces, en resumen, para construir una transacción, necesitaríamos construir los siguientes ítems. Para una salida, necesitaríamos una dirección y una cantidad para enviar a esa dirección. Si hay una necesidad de un cambio y la mayoría de las transacciones lo hacen, entonces tendríamos que construir una segunda salida que contenga una dirección de cambio y una cantidad. También necesitaríamos un número variable de entradas cuya suma de cantidad de Bitcoin debe ser mayor que la cantidad a enviar más la tarifa de transacción. Recuerda que una entrada se referirá a una salida no gastada de una transacción anterior enviada a una de tus direcciones. Se necesitará un cambio si la suma de los montos ingresados es mayor que la cantidad a enviar más la tarifa de transacción. Si por suerte o por diseño, la suma de los montos de entrada es igual a la cantidad a enviar más la tarifa de transacción que la transacción no tendrá un resultado de cambio. Y el remitente se beneficiará de pagar menos en tarifa de transacción por una transacción con solo una salida. Nuevamente, para calcular la tarifa de transacción se necesitará la tasa de comisión en Satoshi por v bytes. Obtendremos este valor usando la estimación de la API de gRPC para teléfonos inteligentes de Bitcoin Core y convertiremos el resultado en Satoshi por mordida V también necesitará el tamaño de la transacción en v bytes. En el siguiente video, implementaremos la nota estima Smart Fee, cliente y un servicio para calcular el tamaño de la transacción. Posteriormente, combinaremos ambos para calcular las tarifas de transacción. Verás, sí. 47. 45 Enviar bitcoin parte 2 skillshare 2: En este video, crearemos una calculadora de tamaño de transacción y construiremos el cliente de nodo para el método RPC de nodo Bitcoin de feed inteligente de estimación . En el paquete api dot services, vamos a crear la clase de calculadora de tamaño de transacción. Esta clase se encargará de calcular los tamaños de las transacciones de acuerdo a sus tipos y números de entradas y salidas. Estos tamaños se utilizarán posteriormente para calcular el monto de la tarifa que tenemos que incluir en nuestras transacciones. Vamos a agregarle una anotación de servicios. Primero, definiremos algunas constantes en esta clase. Estas constantes contendrán los tamaños de cada parte de una transacción. Dado que estamos trabajando solo con transacciones Segway por ahora, estas constantes se referirán solo a partes de transacciones Segway. Entonces comencemos a definir el tamaño de los gastos generales de la transacción. La sobrecarga es la parte de la transacción cuyo tamaño no cambia con el número de entradas o salidas. La primera constante se llamará inversión, que es parte de la sobrecarga. Codifica qué versión tiene la transacción. Tiene cuatro bytes de tamaño. Entonces tenemos el conteo de entrada, que como su nombre indica, especifica el número de entradas en la transacción. Tiene un número variable de bytes, pero para hasta 252 entradas, su tamaño es de un byte. Entonces tenemos el campo de conteo de salida, que tiene el mismo tamaño y reglas que el conteo de entrada. Como su nombre indica, especifica el número de salidas en la transacción. Entonces tenemos el campo de tiempo de N lote, que tiene cuatro bytes. Este campo se utiliza a veces para codificar el tiempo después del cual se puede gastar la transacción. Entonces tenemos el marcador y bandera Segway, que solo está presente para transacciones Segway. Tiene dos bytes de tamaño. Ahora vamos a establecer los tamaños de campo de entrada, comenzando por el outpoint, que tiene 36 bytes de tamaño. El punto es la combinación del ID de transacción anterior y el índice de salida. Indica el UTXO utilizado para esa entrada. Entonces tenemos el campo de longitud ScriptSig, que estamos hasta 252 bytes, tiene un byte. Indica el tamaño ScriptSig para la entrada. Entonces tenemos el campo ScriptSiG. Para transacciones Segway. Su talla es cero. Recuerde que para las entradas de segmento, el contenido de ScriptSig se mueve al campo testigo. Ahora agreguemos el campo de secuencia final. Tiene cuatro bytes de tamaño y se utiliza para establecer si la transacción es reemplazable en caso de que el remitente quiera cambiar su tarifa. A continuación, agreguemos el campo de conteo de testigos hasta por 250 para atestiguar elementos. Tiene un byte de tamaño. Entonces tenemos el campo de ítems testigo, que tiene un tamaño de 107 bytes para entradas P2, WP k, h. Este campo está compuesto por la firma, que puede tener 71 o 72 bytes de tamaño, y la clave pública, que es de 33 bytes de tamaño, 72 bytes, se elige como tamaño para las firmas, ya que preferimos sobreestimar un poco el tamaño de la transacción. Por lo que se garantiza que el F0 calculado sea suficiente para la transacción. Los dos bytes restantes que codifican el tamaño de la firma y la clave pública. Explique los ítems testigo valor constante de 107. Ahora vamos a establecer las constantes con los tamaños de salida. El valor n es la cantidad de bitcoin que se envía en esa salida. Tiene ocho bytes de tamaño. Entonces tenemos la longitud de la clave pub script, que tiene un byte de tamaño para hasta 252 bytes en longitud de clave pub script. A continuación, tenemos la clave pub script, que tiene 22 bytes de tamaño por un segundo, ¿qué direcciones? Ahora, antes de continuar implementando el cálculo del tamaño de transacción, vamos a crear la prueba de la calculadora de tamaño de transacción en el paquete de prueba API. Extenderá la clase de especificación. Agreguemos un campo de calculadora de tamaño de transacción en esta clase. Y usemos un método de configuración para instanciarlo. Ahora, vamos a crear un nombre de prueba debe calcular el tamaño de la transacción para P2, WP k, h salidas de transacción y entradas. En el bloque de un solo bloque, llamaremos al método de cálculo en el servicio de calculadora de tamaño de transacción y almacenaremos el retorno en la variable de resultado. Como parámetros pasarán las entradas y salidas, cuales definiremos en el bloque where. En el bloque se comprobará si el resultado es igual a la variable de tamaño esperado. En el bloque where se sumarán los siguientes casos de prueba. Para las entradas y salidas las variables establecerán listas con un número variable de direcciones. Ya que por ahora, no nos importa el tipo de direcciones, simplemente agregaremos una carta que represente cada dirección. Los valores de tamaño esperados aquí se calcularon previamente para cada combinación de entradas y salidas y se validaron usando el Bitcoin Core CLI. Ahora, vamos a crear el método de cálculo en la clase de calculadora de tamaño de transacción. Devolverá un entero grande y recibirá como parámetros una lista de direcciones de entrada y una lista de direcciones de salida. Ahora, primero calculemos el tamaño de los gastos generales. Es igual a la suma de estas constantes. Recuerda que el valor que queremos calcular aquí es el tamaño V. Por lo que los elementos de las transacciones Segway, como el Segway, marcador y bandera, deben dividirse por cuatro. Como tal, dividamos esta constante por cuatro. Ahora, calculemos el tamaño de entrada. Será la suma de estas constantes. Ahora, calculemos el tamaño de todas las entradas multiplicando la variable de entrada por el número de direcciones de entrada. Ahora, calculemos el tamaño del testigo agregando las constantes de recuento de testigos y elementos testigos. Como segue ¿qué elementos? Dividamos su suma por cuatro. El tamaño total del testigo es igual a la variable testigo multiplicada por el tamaño de las direcciones de entrada. Ahora, calculemos el tamaño de salida. Será igual a la suma de estas constantes. La variable de todas las salidas será igual al tamaño de salida multiplicado por el número de salidas. Finalmente, el resultado del tamaño de transacción será igual al BigDecimal algunos de los valores calculados previamente. También pongamos la escala del resultado a cero con el modo de redondeo a la mitad hacia arriba. Esto hará que el resultado tenga cero decimales redondeando al entero más cercano. Si el valor decimal resultante es cinco, entonces redondeará al entero anterior. Ahora, devolvemos el resultado convertido a entero grande. Ahora, vamos a ejecutar la prueba de la calculadora de tamaño de transacción. Genial, La prueba ha pasado. Ahora vamos a crear el cliente de tarifa inteligente de estimación de nodo en el paquete de cliente nodo punto. Inyectemos el cliente del nodo en él. Y vamos a crear el método de la tarifa inteligente de estimaciones. Devolverá un nuevo nodo que creará el objeto FI, y tomará un entero como parámetro. Ahora volvamos a hacer llamada al método request en el cliente del nodo. El nombre del método será estimado smart fee. Su segundo parámetro será un nuevo objeto de referencia de tipo parametrizado. Es tercero será una cadena vacía y su último parámetro, la variable blocks. Ahora vamos a crear el registro del nodo V en el paquete de nodos de punto de dominios. Sus campos serán una tasa de tarifa doble y una lista de errores. Ahora en el paquete api dot services, vamos a crear una interfaz llamada servicio de tarifa de estimación. Vamos a agregarle el método de estimación. Devolverá un decimal grande. Ahora, vamos a crear una implementación de esta interfaz. Nombres notan estimación tarifa de servicio en el mismo paquete. Vamos a implementar su método. Esta clase se utilizará más adelante para estimar la tarifa usando el nodo estima el cliente Smart Fee. Si queremos cambiar el método de estimación de tarifas o agregar más opciones para hacerlo más adelante, simplemente creamos otra implementación de la interfaz de servicio de tarifas estimadas. Primero, llamaremos al método de estimación del teléfono inteligente desde el cliente creado previamente y se almacenará en la variable nodo V. Vamos a inyectar este cliente en esta clase pasará a este método para que intentemos obtener una tasa de comisión que hará que nuestra transacción se confirme en el siguiente bloque. Si por alguna razón la tasa de tarifa devuelta resulta ser igual a nula, devolveremos la tasa de tarifa de reserva. Inyectemos esta variable en esta clase. Lo inyectará desde los archivos de propiedades. Entonces agreguemos esta anotación de valor antes de ella. Después de la declaración if devolverá el gran valor decimal de la tasa de comisión. Ahora agreguemos la propiedad bitcoin dot fallback fee rate property a todos los archivos de propiedad del proyecto. Hagámoslo igual a 0.0 002. 48. Selección de monedas y polvo: En esta presentación, continuaremos explicando conceptos importantes para comprender las transacciones de Bitcoin y continuar construyendo nuestra función de transacción de pecado. Entonces hablemos de la selección de monedas. selección de monedas es el proceso de seleccionar UTXOS para construir una transacción. La regla general para esta selección es que la suma de montos UTXOS Bitcoin debe ser mayor que la cantidad de arena más la tarifa de transacción más el cambio si es necesario. Hay muchos métodos diferentes de selección de monedas. Cada uno tiene ventajas y desventajas. El algoritmo que elegiremos para nuestra billetera se llama sorteo aleatorio único. Probablemente sea el algoritmo de selección de monedas más simple y lo suficientemente bueno para nuestros propósitos. Este algoritmo se presentó por primera vez en una tesis de maestría titulada y evaluación de estrategias de selección de monedas por Mark Earhart. Te recomiendo leer esta tesis si quieres saber más sobre estrategias de selección de monedas. Este método de selección de monedas se agregó a Bitcoin Core en septiembre de 2021 como una estrategia de selección de monedas alternativas. Consiste en barajar el gasto o UTXOS, luego seleccionar UTXOS uno por uno hasta que la suma de los montos UTXOS seleccionados sea mayor o igual a la cantidad a enviar más la tarifa de transacción más el cambiar si es necesario. Si la cantidad de cambio es menor que el límite de polvo, la salida de cambio se elimina de la transacción y su monto se agrega a la tarifa de transacción. Pero espera un momento, ¿qué es el polvo? Una salida de polvo es una salida cuya cantidad de Bitcoin es menor que el costo para gastarlo. El siguiente ejemplo muestra cómo las salidas de polvo no son económicas de gastar. Digamos que tienes un UTXO que contiene 50 Satoshi's y quieres mandar estos 50 Satoshi's a un amigo. Al construir la transacción, descubres que la tarifa de transacción requerida para enviarla equivale a 100 Satoshi's. Por lo tanto, no tiene sentido que gastes el UTXO con 50 Satoshi's ya que pagarás más en cuotas que la cantidad enviada. Además, tu amigo tampoco se beneficiará de recibir un UTXO con 50 Satoshi's ya que tendría el mismo problema que tú lo estás gastando. Este ejemplo muestra que es perjudicial para la red Bitcoin crear salidas de polvo, ya que nadie en la red se beneficia de ella. Por lo tanto, la mayoría de los nodos de Bitcoin no relacionan transacciones que contienen polvo. Esto ayuda a proteger la red de los ataques de polvo. ataque de polvo es el proceso de enviar polvo maliciosamente a las direcciones de la billetera para rastrear sus transacciones. Este ataque se muestra en este ejemplo. Supongamos que la agencia gubernamental envía polvo a la dirección X que le pertenece a la persona. ¿Por qué? Cuando la billetera electrónica construye ingenuamente una transacción, incluye la salida de polvo y otras cinco como entradas. Ahora bien, la agencia gubernamental sabe por qué cinco direcciones anteriores y todas sus transacciones anteriores. Además, el gobierno conoce ahora la dirección de cambio de esa transacción y contrata otras transacciones con ella. Pero, ¿cuáles son los criterios para considerar una salida como polvo? eso se usa el límite de polvo. Cada salida cuya cantidad de Bitcoin es menor que el límite de polvo se considera polvo. núcleo de Bitcoin utiliza la siguiente fórmula para calcular el límite de polvo. El límite de polvo en Satoshi de una salida de transacción es igual al tamaño de salida de la transacción más el tamaño de entrada necesario para gastarlo tanto en v bytes multiplicado por la industria frondosa en Satoshi per KV bytes divididos por 1,000. El resultado representa el costo de salida de transacción que una cantidad de Bitcoin de salida de transacción debe ser igual o superar para no ser considerada polvo. La tarifa de relé de polvo es una propiedad de configuración del nodo Bitcoin. Es la tarifa de transacción utilizada al calcular el límite de polvo. La tarifa predeterminada por relé de polvo se establece en 3,000 Satoshi por KV bytes o tres Satoshi por mordida de V. Esto hace que el límite de polvo predeterminado para las salidas de segue sea igual a 294. Satoshi. El límite de polvo por defecto para non segue qué salidas son iguales a 546 Satoshi. Para más detalles sobre el cálculo del límite de polvo, este enlace del código Bitcoin Core tiene un comentario explicando cómo se calcula el límite de polvo. Ahora vamos a resumir los pasos generales del algoritmo de sorteo aleatorio único. El primer paso es barajar todos los UTXOS de cartera en una lista. Después, para cada UTXO disponible de la lista barajada, agregue ese UTXO a una lista de UTXO seleccionados. Calcular el objetivo ajustado, que es igual a la cantidad de arena más la tarifa de transacción más el cambio si es necesario. Si la cantidad total de Bitcoin en la lista UTXOS seleccionada es mayor o igual que el objetivo ajustado. Detener. Finalmente, utilice los UTXOS seleccionados como entradas de la transacción deseada. Algunos puntos de atención sobre este algoritmo, los objetivos ajustados con y sin la salida de cambio deben calcularse para una mejor precisión ya que las tarifas de transacción difieren entre las transacciones con 1.2 salidas, si el cambio generado está entre cero y el límite de polvo, detenemos la iteración ya que no incluiremos un cambio la transacción y así no necesitamos más UTXOS. Esto es necesario para no generar una salida de polvo para el cambio por accidente. El inconveniente del algoritmo de sorteo aleatorio único aparece en algunos casos patológicos, por ejemplo, cuando tienes un único UTXO grande y muchos UTXO pequeños. una transacción con muchos insumos y una tarifa de puede crear una transacción con muchos insumos y una tarifa de transacción alta en lugar de usar el gran UTXO para evitar la necesidad de muchos insumos. Cuando ese es el caso, se recomienda un enfoque diferente para construir una transacción. Por ejemplo, elija manualmente los UTXOS que formarán parte de algunas transacciones específicas. En el siguiente video, implementaremos una calculadora de polvo y el algoritmo de sorteo aleatorio único, C, sí. 49. 47 Enviar bitcoin parte 3 skillshare 2: En este video, comenzaremos a implementar una calculadora de polvo y el algoritmo de sorteo aleatorio único. Pero primero, vamos a refactorizar el registro UTXO. Ya que haremos muchos cálculos con el campo de cantidad UTXO. Y los cálculos se hacen mejor con decimales grandes en lugar de dobles cambiarán la cantidad tipo dos decimales grandes. Ahora, tenemos que refactorizar todos los usos del campo de cantidad en el proyecto. Entonces hagámoslo. Cambiemos el formato o parámetro de formato de Bitcoin a BigDecimal y ajustemos este parámetro en consecuencia. Hagamos lo mismo con todos los métodos que el IDE marcó como errores en el proyecto. Aquí agregaremos grandes decimales usando el método add. Y pasemos el gran valor decimal cero en lugar del cero primitivo a estas llamadas a métodos. Ahora, tenemos que cambiar el tipo de este campo equilibrado y todos sus usos. Vamos a refactorizar este método para hacer la suma usando valores decimales grandes. Ajustemos también este código para hacer lo mismo, pero con grandes valores decimales. Bien, la refactorización está hecha. Ahora en el paquete de servicios api dot. Vamos a crear la clase de calculadora de polvo. Vamos a agregarle la anotación de servicio. Vamos a crear estos métodos de polvo en él. Como su nombre indica, devolverá true si una cantidad se considera polvo falso, lo contrario, devolverá un Booleano y tomará un entero grande como parámetro que representa la cantidad en De Satoshi. Este método evaluará si la cantidad en Satoshi's de un producto es menor que el costo para gastarlo. El costo del gasto es igual al tamaño V de la salida más el tamaño v de la entrada necesaria para gastarlo, que almacenará en estos tiempos constantes los pies de relé de polvo en bytes por kilo v de Satoshi dividido por 1,000. Como por ahora trabajaremos solo con salidas sigmoides, solo nos preocuparemos por el límite de polvo para las salidas de segue. Así que vamos a crear esta constante que será igual a 98. Este valor se toma directamente del archivo punto cpp de política Bitcoin Core mencionado en la última presentación. Inyectemos también la tarifa del relé de polvo en esta clase. Estará a lo largo y su valor será inyectado desde el archivo de propiedades. Vamos a agregar la siguiente anotación de valor antes de ella. Ahora agreguemos este valor a todos los archivos de propiedades. Vamos a establecerlo en 3,000, el mismo valor predeterminado utilizado en el Bitcoin Core Node. Ahora en el paquete api dot services, vamos a crear la interfaz del selector de monedas. Creará esta interfaz para que permita mayor flexibilidad. Si queremos crear más implementaciones de selector de monedas más adelante. Vamos a agregarle el método select. Devolverá una lista de UTXOS seleccionados. Y nos llevará parámetros, una lista de UTXOS, un entero grande por la cantidad a enviar, un decimal grande para la tasa de tarifa, y dirección a enviar, y una dirección de cambio. Ahora en el mismo paquete, vamos a crear el único selector de monedas de sorteo aleatorio, que implementará esta interfaz. Implementemos su método y le agreguemos una anotación de Servicio. Inyectemos la calculadora de tamaño de transacción en esta clase. Y vamos a inyectarle la calculadora de polvo. Antes de continuar implementando el método de selección, vamos a crear el único sorteo aleatorio una clase de prueba de selector de monedas. En la clase de prueba API. Extenderá la clase de especificación. Inyectemos el único sorteo aleatorio en esta clase. Y usemos el método de configuración para instanciarlo. Pasemos la calculadora de tamaño de transacción y la calculadora de polvo con una tarifa de relé de polvo de 3,000 como sus parámetros. Ahora, vamos a crear una prueba Tidal debería seleccionar n entradas esperadas, monedas para transacción con salidas esperadas y salidas. Ahora vamos a crear una clase de utilidad que nos ayude a probar e implementar el selector único de monedas de sorteo aleatorio. Vamos a llamarlo Satoshi y creado en el paquete utils. Ahora, vamos a crear el método de los dos Satoshi. Tomará un decimal grande como parámetro y devuelve un entero grande. Este método convertirá una cantidad en Bitcoin a la misma cantidad en Satoshi's. Para ello, simplemente devolvemos la cantidad en Bitcoin multiplicada por 100 millones y convertimos multiplicada por 100 millones y el resultado a un entero grande. Creemos también un método para hacer la operación inversa, que es convertir Satoshi's a Bitcoin. Para eso, solo devolveremos la cantidad envuelta en un nuevo decimal grande dividido por 100 millones. En el método de división pasará ocho como segundo parámetro para hacer que el resultado tenga ocho decimales. También pasaremos el modo de redondeo innecesario como tercer parámetro. Ahora, vamos a crear un método para convertir una tasa de comisión en Bitcoins por bici KV a Satoshi por V byte. Se llamará BTC por KB a los de Satoshi por byte. Devolverá un entero grande y tomará como parámetro un decimal grande. Primero, multiplicaremos la tasa de comisión por 100 millones. Después dividiremos el resultado por 1024 con dos decimales y un modo de redondeo de piso. Entonces vamos a convertir el resultado a un entero grande y almacenarlo en la variable derecha. Si el resultado es menor que uno, entonces lo hacemos igual a uno. Finalmente, devolvemos la tasa convertida. En el siguiente video, terminaremos de probar e implementar el selector único de monedas de sorteo aleatorio C. Si. 50. 48 Enviar bitcoin parte 4 Skillshare 2: En este video, terminaremos implementar el algoritmo de sorteo aleatorio único. En la prueba de selección de monedas de sorteo aleatorio único en un bloque dado, primero crearemos UTXOS usando este método y almacenaremos el resultado en la variable UTXOS. Estos serán los UTXOS disponibles que pasarán como primer parámetro al método probado. Así que vamos a crear este método. Tomará como parámetro una lista de enteros grandes, que definirá la cantidad de cada UTXO. Entonces, para cada elemento de la lista, llamaremos al método create UTXO para crear un único UTXO. Vamos a crear este método. Instanciemos un UTXO con estos parámetros. Puede copiar estos valores de los recursos de esta lección. Ahora, vamos a crear un UTXO adicional y agregarlo a la lista de UTXOS usando este código. La razón para agregar un UTXO adicional a la lista es que queremos permitir el método select lo agregue erróneamente a la lista de UTXOS seleccionada. Si ese es el caso, sabremos que el método probado no está funcionando como se esperaba. Definamos estas dos direcciones. Uno para ser la dirección a enviar y el otro para ser el cambio de dirección. Puedes copiarlos desde la página Proyecto y Recursos. Fijemos la tasa de comisión en 0.0 002. En el bloque de viento, llamaremos al método single random draw select con estos parámetros. En el bloque entonces comprobará si el tamaño UTXOS seleccionado es igual al número esperado de entradas variable en el bloque where. Agreguemos estos casos de prueba. Los puedes encontrar en la página Proyecto y Recursos. Estos casos de prueba cubrieron transacciones con 12.3 entradas y con 1.2 salidas. los montos de entrada para transacciones con Se espera que los montos de entrada para transacciones con una salida no generen cambios o generen cambios con polvo cuyo valor se agrega a la comisión. que los montos de entrada para transacciones con Se espera que los montos de entrada para transacciones con dos salidas generen non does change, que regresa al remitente a través de una segunda salida. Vamos a hacer la prueba. Ha fracasado como se esperaba. Ahora, vamos a implementar el método de selección de sorteo aleatorio único. Primero, filtraremos todos los UTXOS recibidos para crear una lista con solo UTXOS que tengan una o más conformaciones. Así que vamos a crear este método. Para hacer eso. Llamaremos al método de filtro en la transmisión de UTXOS, devolviendo una lista con solo UTXOS confirmados. Ahora, vamos a crear esta variable para almacenar la tasa de tarifa en Satoshi por V byte. Para eso, usaremos el método BTC por KB a Satoshi por bicicleta de la clase Satoshi. Ahora, vamos a almacenar los UTXOS barajados en esta variable, asignándole el retorno de esta llamada al método. Vamos a crear este método. Primero, instanciaremos un nuevo ArrayList que contenga el contenido de la lista UTXOS. Después llamaremos al método de reproducción aleatoria de colecciones, pasando la nueva lista como su parámetro. Después devolveremos la lista de monedas barajadas. Ahora instanciemos una ArrayList que almacenará los UTXOS seleccionados. Y vamos a crear esta variable para almacenar el saldo total de entrada. Ahora, para cada UTXO de la lista de monedas barajadas, agregaremos el UTXO a la lista UTXO seleccionada. Y agregaremos su cantidad en Satoshi a la variable balanceada de entrada total. Si el saldo total de entrada es menor que la cantidad ascendida, continuamos la ejecución desde la siguiente iteración del bucle. Después de la sentencia if, cuando el saldo total de entrada supere la cantidad a enviar instanciará una ArrayList con las direcciones de salida y agregará la dirección a enviar a esa lista. Y crearemos una lista con las direcciones de las entradas seleccionadas usando este mapeo de flujo. Ahora, calculemos la cuota total en Satoshi's y almacenemos en esta variable. Para eso, llamemos al método de tarifa total, pasando la tasa de tarifa en Satoshi's por V mordida las direcciones de entrada y las direcciones de salida como sus parámetros. Vamos a crear este método. En su interior devolverá la calculadora de tamaño de transacción calcular método de llamada pasando las direcciones de entrada y las direcciones de salida como sus parámetros. Después multiplicaremos el resultado con la tasa de comisión en Satoshi por V mordida. Ahora crearemos la variable objetivo ajustada, que será igual a la suma del monto a enviar y la tarifa total. Ahora agreguemos la dirección de cambio a la lista de direcciones de salida. Calcularemos la tarifa total con cambio, llamando al método de tarifa total, pasando estos parámetros. Y calcularemos el objetivo ajustado con cambio, que será igual a la suma de la cantidad de arena y la cuota total con cambio. Ahora bien, si el resultado del método de transacción cumplida balanceada de entrada con estos parámetros es verdadero, saldremos del bucle usando la palabra clave break. Vamos a crear este método. Devolverá el resultado de la siguiente declaración. Si el saldo total de entrada es igual o mayor que el objetivo ajustado y el generado cambia de polvo, entonces significa que los UTXO seleccionados son suficientes para cumplir con esta transacción. Otra condición para que los UTXOS seleccionados cumplan con la transacción es que son cantidades que la suma es igual o mayor que el objetivo ajustado con cambio. Vamos a crear el método de cambio es polvo devolverá la calculadora de polvo es llamada método de polvo pasando la gran diferencia entera entre el saldo total de entrada y el objetivo ajustado como su parámetro. Finalmente, simplemente devolvemos los UTXOS seleccionados de este método. Ahora, vayamos a la prueba del selector de monedas de un solo sorteo aleatorio y ejecutemos esta prueba. Grado. Ya pasaron las pruebas. 51. Cómo se construyen y validan las transacciones de Segwit: En esta presentación, veremos más detalles sobre cómo crear una transacción. Entonces digamos que ya usamos el selector de monedas para seleccionar algunos UTXO para gastar como entradas en una transacción. En nuestro monedero, también tenemos la capacidad de derivar las claves privadas necesarias para gastar estos UTXOS. Estas claves privadas serán necesarias para firmar la transacción posteriormente. Ya elegimos una dirección para enviar algunos Bitcoins. Y tenemos la dirección de cambio a donde se enviará el cambio. Después de definir estas cosas, es el momento de construir nuestra transacción. Veamos los campos que forman parte de una transacción de Bitcoin. En primer lugar, el campo de la versión. Se utiliza para definir las reglas que sigue la transacción. Actualmente, la versión uno, que utilizaremos es para transacciones comunes. versión dos es para transacciones que siguen al BIP 68, que implementa reglas para validar una transacción solo después de cierto tiempo. El campo de vida útil se utiliza para un propósito similar. Su valor puede representar un cierto tiempo para agregar una transacción a un bloque o cero para ignorar esta regla, entonces tenemos el seg sería flag y marcador. Sólo está presente en las transacciones Segway. Si su valor es 0001, entonces marca esta transacción como habiendo dicho qué entradas, cada transacción tiene una o más entradas de transacción. Cada entrada de transacción tiene un ID de transacción que define una transacción anterior a partir de la cual la entrada actual está gastando Bitcoins. El índice de salida indica qué salida de la transacción anterior. El insumo actual está gastando Bitcoins de. Juntos, el ID de transacción y el índice de salida se denominan punto de salida. Puede ver el punto fuera como una coordenada para identificar a qué UTXO y entrada se refiere. A continuación, para cada entrada, tenemos el campo ScriptSig. En entradas de segmento. Este campo está vacío y su contenido se mueve al campo testigo. En las transacciones no segmentadas, su contenido es necesario para desbloquear el gasto del UTXO. La entrada se refiere a. El campo de secuencia n define cuándo la entrada es válida para gastar. Cuando este valor de campo es igual al valor hexadecimal máximo para su tamaño, este campo se ignora. Una transacción también tiene una o más salidas. Cada salida contiene una clave de pub script, que tiene un código de script que define las reglas para gastar esa salida en una transacción futura. Cada salida también contiene un campo de cantidad que define el número de Satoshi bloqueado en esa salida. Por último, las transacciones también contienen un campo testigo. Para transacciones que no sean Segway, este campo está vacío. Para las transacciones Segway, el testigo contiene todo el contenido que en las transacciones no secuitur está en el scriptSIG de cada entrada. Ahora hablemos de cómo construir entradas de transacción y el campo testigo para entradas de segmento. Para cada UTXO seleccionado, tenemos que construir una entrada de transacción. El campo ID de transacción de la entrada de transacción será igual al ID de transacción UTXO. El campo de índice de salida será igual al índice de salida UTXO, también conocido como Vout en la documentación de la API de Bitcoin Core RPC. El scriptSig estará vacío y la secuencia final será igual a este valor hexadecimal, que es el valor máximo permitido para ese campo. También tenemos que construir un testigo por cada entrada, el campo testigo contendrá una firma obtenida usando la clave privada utilizada para derivar la dirección UTXO. Y una clave pública que se derivó utilizando la clave privada anterior y que también puede generar la misma dirección UTXO mencionada. Veremos más detalles sobre el proceso de firma en una presentación futura. Observe las firmas ficticias y los bupkis, cuyos valores pueden ser un montón de ceros, se pueden usar como marcadores de posición para crear y firmar transacciones. Este truco facilita el cálculo del tamaño de la transacción v antes de firmar las transacciones. Ahora hablemos de cómo crear segue qué salidas. Primero. En una nota al margen, es posible crear una transacción con diferentes tipos de entradas y salidas, por ejemplo, en una misma transacción, puede tener entradas y salidas de segmento y no segmento. Volver al tema principal. Generalmente, queremos crear una salida para la dirección a la que queremos enviar bitcoins y una salida para la dirección de cambio. Si la transacción necesita un cambio. Cada salida de transacción tiene un campo de clave de pub script. Cada segmento script pub key, también conocido como pay to witness pub key hash o P2, WP k H tiene una versión testigo de cero. La versión testigo es una para guiones de raíz principal. Se pueden agregar nuevas versiones para futuros scripts si es necesario. El segundo elemento clave pub script para salidas sigmoides es un hash de clave pública, que es obtenido por Beck 32 decodificando la dirección para esa salida. La salida de la transacción también tiene un campo de cantidad en Satoshi que representa la cantidad enviada a esa dirección de salida. Ahora, terminemos esta presentación hablando sobre la ejecución y validación del script del segmento. Cuando un nodo recibe una transacción, comienza a validarla. Para cada entrada en una transacción, el nodo combina el testigo de una entrada con la clave pub script del UTXO referido por el outpoint y net input ejecuta el script combinado y lo valida . Veamos cómo se hace eso. Aquí está el script pub key de un UTXO y el campo testigo que quiere gastar ese UTXO ambos generan el siguiente guión combinado. Es posible que se esté preguntando de dónde provienen los códigos de operación del script combinado. Resulta que cuando un nodo identifica la versión cero en la clave pub script de segmento, desencadena una regla especial que genera parte del código combinado a continuación. A continuación, el script combinado se ejecuta igual que los scripts que no son secuiturs. A partir del script combinado, la firma y las claves públicas se agregan a una pila de ejecución. Entonces el opcode OPT up duplica la clave pub en la pila de ejecución. Hasta hash 160 hashes, la última clave de pub agregada a la pila. Luego, desde el script combinado, se agrega el hash de la clave de pub a la pila. Up equal verify opcode elimina los dos últimos elementos de la pila de ejecución y los compara. Si son iguales, el script continúa ejecutándose. Finalmente, el opcode sig objeto comprueba si la firma es válida para la clave pub que queda en la pila. Si es válido, devuelve true a la pila de ejecución. Después de agregar todos los elementos del script a la pila de ejecución, la entrada de transacción se consideraría válida si el último elemento agregado es verdadero. Este proceso debe repetirse para cada entrada de transacción. Para que una transacción se considere válida, todos sus insumos deben ser válidos. Así como un recordatorio visual, repasemos de dónde vino cada elemento en la clave del pub script y testigo la clave del pub script y testigo durante la construcción de la transacción. El hash de pub key presente en el script pub key vino de atrás 30 a decodificar la dirección del UTXO que se está gastando. La firma en el testigo llegó aplicando el algoritmo ECDSA, cual necesita una clave privada válida. La clave pública y el testigo procedían de la clave pública derivada de la mencionada clave privada. La misma clave pública se utilizó en el pasado para generar la dirección del UTXO que se está gastando aplicando secuencialmente el algoritmo hash 160 y la codificación back 32. 52. 50 Enviar bitcoin parte 5 skillshare 2: En este video, crearemos un servicio de creación de transacciones. En un principio, este servicio sólo se ocupará de entradas y salidas de segmento, pero más adelante en el curso, lo mejoraremos. Entonces, en el paquete de servicios api dot, vamos a crear el servicio de creadores de transacciones. Vamos a agregarle la anotación de servicio. Inyectemos también la calculadora de polvo en él. Ahora en el paquete de prueba API, vamos a crear la clase de prueba de servicio de creadores de transacciones. Extenderá la clase de especificación. Inyectemos el servicio de creadores de transacciones en él, y vamos a instanciarlo en el método de configuración. Necesitará instanciarlo con una nueva calculadora de polvo pase 3,000 ya que es el parámetro de tarifa de relé de polvo. Antes de hacer esta prueba, vamos a la prueba de selector de monedas de sorteo único aleatorio para hacer un poco de refactorización. Cortemos estos dos métodos de esta clase y los peguemos en la nueva clase utils que crearemos en el paquete de prueba BYOD W. Hagamos estáticos estos dos métodos. Ahora, arreglemos la única moneda de droga aleatoria. Seleccione su prueba para usar estos métodos de esta clase. Ahora, vayamos a la prueba de servicio de creadores de transacciones. Vamos a crear una prueba llamada debe crear transacción con hashtag n entradas, entradas y hashtag esperado n salidas, salidas. En el cuerpo dado. Primero vamos a crear esta variable UTXOS y asignarle la llamada al método utils dot create utxOS que se le devuelve, pasando la variable input amounts como su parámetro. Ahora, vamos a crear esta dirección para enviar variable. Su contenido será igual a la variable con el mismo nombre en la prueba de selección de monedas de sorteo único aleatorio. También vamos a crear la variable de cambio de dirección, que será igual a la variable con el mismo nombre en el único sorteo aleatorio de una moneda, seleccione su prueba. Vamos a crear la variable de tasa de comisión, que será igual a 0.000 a. Definamos también la variable de tarifa total esperada, que será igual a la variable de tamaño esperado multiplicada por la tasa de tarifa en Satoshi por V mordida. Ahora, vamos a crear la variable cantidad total de entrada. Su valor será igual al resultado de esta expresión, que devolverá la suma de cada cantidad UTXO en Satoshi. El monto a enviar variable será igual a 100 millones de Satoshi. Calculemos también la cantidad de cambio esperada. Será igual a la cantidad de entrada menos la cantidad de arena menos la tarifa total esperada. En el bloque de un solo bloque, llamaremos al creador de transacciones, el método create pasará los siguientes parámetros a este método. El resultado se almacenará en la variable de transacción. En el bloque entonces comprobará si el tamaño de la transacción v es igual a la variable de tamaño esperado. Pero primero, actualicemos la versión Bitcoin Java a 0.4, 0.2 para hacer disponible el método get v size. Ahora, verificaremos si el número de salidas de transacción es igual a la variable esperada y salidas. También verificaremos si la primera cantidad de salida es igual a la variable cantidad a enviar. Ahora, si el número esperado de salidas es mayor que uno, comprobará si el monto de cambio es igual al segundo monto de salida en la transacción. En el bloque donde. Agreguemos los siguientes casos de prueba. Puedes copiarlos desde la página Proyecto y Recursos. Estos casos de prueba cubren escenarios con y sin salidas de cambio y con cantidades de entrada que generan cambios o no. También cubrieron transacciones con 12.3 insumos. Ahora vamos a crear el método de creación del servicio de creadores de transacciones. Cambiemos el nombre de estos parámetros. Antes de implementar este método, vamos a crear la clase de tarifa en el paquete utils. Aquí crearemos un método para calcular la tarifa total de transacciones en Satoshi's, llamémoslo tarifa total calculada. Recibirá una transacción en la tasa de comisión en Bitcoin por mordida KV creará el siguiente código dentro de un bloque try catch. Primero, convertiremos la tasa de pago de Bitcoins por bicicleta KV a Satoshi is privy byte. Luego devolveremos el resultado multiplicando el tamaño de la transacción v por la tasa de tarifa en Satoshi por mordida de V atrapará una IOException que puede ser lanzada por el buen método de tamaño V y rápido en una nueva excepción de tiempo de ejecución. Volver al servicio de creadores de transacciones. En este método primero se construirán las entradas de transacción utilizando este método, pasando los UTXOS recibidos como su parámetro. Vamos a crear este método. Devolveremos el resultado de la siguiente transformación de flujo UTXOS no la transmisión en una nueva entrada de transacción pasará el ID UTXO recibido como su primer parámetro. El valor entero grande de la UTXO jurada como su segundo parámetro. Estos dos parámetros definen el outpoint de entrada de transacción. A continuación, pasaremos un nuevo script instanciado con una lista vacía. Este parámetro es la entrada de transacción ScriptSig, que está vacía para las entradas de segmento. A continuación, pasaremos un entero grande instanciado con estos parámetros, que define la entrada en secuencia. Este valor es el valor máximo permitido para este campo, haciendo que los nodos lo ignoren. Ahora, para cada entrada de transacción en el flujo se utilizará el método pico para establecer el testigo, se instanciará al testigo con una lista que contiene constantes para una firma ficticio y una clave de pub ficticio. Ahora vamos a crear estas constantes. La firma ficticio será igual a la cadena hexadecimal cero repetida 144 veces, cuyo tamaño en bytes es igual a 72. La clave de pub ficticio será igual a la cadena hexadecimal cero repetida 66 veces cuyo tamaño en bytes es igual a 33 establecerá estos valores ficticio porque serán necesarios para hacer correctamente el transacción v tamaño cálculo, que hará en el método create, el proceso de firma se hará por separado más adelante cuando los valores reales, vamos a sustituir los ficticio. Finalmente, convertiremos el stream en un ArrayList y lo devolveremos. Ahora, construiremos la salida de la transacción para la dirección a enviar usando el método buildup PUT, pasando como parámetros la dirección a enviar y la cantidad a enviar. Vamos a crear este método. Primero, vamos a analizar el prefijo de dirección usando el método parse prefix, que creará. Este método verificará si la dirección comienza con uno de los prefijos de segmento válidos, y devolverá el prefijo de dirección o una cadena vacía si no se encontró un prefijo válido. Ahora vamos a construir un objeto script usando la clase de script P2, WP k h método de script. Como su parámetro pasará el resultado del back 30 para decodificar la llamada al método, pasando el prefijo y la dirección a este último. El retorno del método back 30 to decode es una matriz de objetos donde el segundo elemento es el hash de la clave pub, que pasará al método de script P2 WP k h. Este método devolverá el equivalente de la clave pub script, donde el primer parámetro es cero y el segundo parámetro es el hash de la clave pub, como explicamos en la última presentación. Finalmente, devolveremos una nueva salida de transacción instanciada con la cantidad y el script creado. Ahora, crearemos una ArrayList para almacenar las salidas de la transacción, instanciaremos , agregándole la dirección para enviar la salida que acabamos de crear. A continuación, crearemos la transacción pasará como sus parámetros, el entero grande, que es la versión de la transacción. Las entradas de transacción, las salidas de la transacción. El cero entero grande es el tiempo de bloqueo que será ignorado. Y el booleano verdadero para definir esta transacción como una transacción segue. Este parámetro hará que la transacción tenga el marcador y el indicador Segway. Ahora, calculemos la tarifa de transacción total usando el método F0 calculado total que hemos creado anteriormente en la clase FI. Pasaremos la transacción y la tasa de comisión como sus parámetros. Calculemos también la zona de entrada para eso mapeará el flujo UTXO en un flujo de cantidades UTXOS. Entonces usaremos el método reducido para sumarlos. Finalmente, convertiremos el resultado es una ptosis o cero si los UTXOS no existen. A continuación, calcularemos el cambio que será igual a la suma de entrada menos la cantidad de arena menos la tarifa total. A continuación, agregaremos la siguiente declaración if. Usando la calculadora de polvo comprobará si el cambio es polvo. Si lo es, entonces devolveremos la transacción tal cual. Si no lo es, agregaremos otra salida a la transacción usando el método de salida de compilación, pasando la dirección de cambio y el número entero grande ya que sus parámetros pasarán uno a la cantidad de salida solo como un valor de marcador de posición, ya que tendremos que recalcular la tarifa de transacción para la transacción que ahora tiene dos salidas lo que exige una tarifa más alta. Entonces, recalculemos la tarifa total utilizando el método F0 calculado total. Nuevamente, vamos a recalcular el cambio que será igual a la suma de entrada menos la cantidad a enviar menos la nueva tarifa total calculada. Ahora, eliminemos la última salida de transacción agregada de las salidas de transacción ArrayList. Comprobemos de nuevo si el nuevo cambio calculado es polvo. Si lo es, entonces devolverá la transacción sin cambios. Si no lo es, agregaremos una nueva salida a la transacción usando el método de salida de compilación. Esta vez, pasaremos el valor de cambio real para la transacción con dos salidas a este método. Por último, devolveremos la transacción. Ahora vayamos a la prueba de servicio de creadores de transacciones y ejecutemos esta prueba. Genial, las pruebas han pasado desde que previamente cambiamos la prueba de selección de monedas de sorteo aleatorio único. También volvamos a ejecutarlo para asegurarnos de que no hemos roto nada. Son geniales. Está funcionando como de costumbre. 53. 51 Enviar bitcoin parte 6 skillshare 2: En este video, comenzaremos a crear la ventana que aparecerá cuando hagamos clic en el botón Enviar. Esa ventana contendrá información sobre la transacción. Estamos enviando un campo de contraseña y un botón Ok para confirmar la transmisión de la transacción. Así que en el paquete FXML, vamos a crear el archivo FXML de punto de diálogo de subrayado de transacción de subrayado de envío . Vamos a borrar la letra estándar generada. Ahora, vamos a crear una etiqueta de dolor de diálogo. Ahora, cambiemos la vista a Scene Builder. Vamos a establecer el diálogo dolor pref altura a 300. Y es ancho pref a 650. Y hagamos el min-height min-width para usar el tamaño de la prensa. Ahora, agreguemos un panel de cuadrícula al contenido del diálogo. Agreguemos cuatro filas más a este panel de cuadrícula. Ahora agreguemos una etiqueta a la primera fila. Cambiemos su texto para enviar el signo de interrogación de transacción. Aumentemos su tamaño de fuente a 16 píxeles. Para las siguientes filas, la idea aquí es agregar etiquetas y datos para la transacción de envío. Agreguemos una etiqueta a la segunda fila y cambiemos su texto a cantidad para enviar dos puntos. En la segunda columna de la misma fila. Agreguemos otra etiqueta. Esta vez su texto estará vacío y le agregaremos un Fx ID para que podamos cambiar su contenido dinámicamente más tarde. Agreguemos otra etiqueta en la tercera fila, esta vez con el texto de las tarifas totales en la celda de la derecha. Agreguemos una etiqueta vacía con otro FX ID. En la fila de abajo. Agreguemos otro par de etiquetas para el campo total. En la siguiente fila. Agreguemos estas etiquetas para la tasa de tarifa. Ahora, hagamos lo mismo para la dirección a enviar. En la última fila. Agreguemos una etiqueta para la contraseña de la billetera. En la celda de la izquierda. Agreguemos un campo de contraseña. Tendrá un ID FX de contraseña de billetera. las etiquetas repentinas les falta dos puntos al final. Vamos a arreglarlos. Ahora. Vamos a la configuración del dolor de diálogo y agreguemos un botón OK aquí. También agreguemos un botón de cancelación. El texto del botón Cancelar está en mi lengua materna. Si ese también es tu caso, puedes cambiarlo haciendo lo siguiente. Vamos a la vista del editor. Primero, agreguemos una idea de Fx de bien al botón Bien. Y agreguemos una idea de Fx de cancelar a la etiqueta del botón cancelar. Ahora, eliminemos esta propiedad. Vamos a establecer la propiedad de los datos del botón a este valor, y vamos a establecer su texto para cancelar. Ahora, en el Scene Builder, podemos ver que el cambio entró en vigor. Ahora, vamos a la pestaña Enviar FXML. En el botón Enviar, vamos a establecer la propiedad action en hashtag send para que cuando hagamos clic en este botón, al método send del controlador de pestañas Enviar se llame al método send del controlador de pestañas Enviar. Así que vamos a crear este método. Antes de implementarlo, vamos a crear un registro DTL de transacción en el paquete de dominios. Ttl significa objeto de transferencia de datos, y es un patrón de diseño común para usar para objetos cuyo propósito principal es transferir datos entre clases y métodos. Como tal, el DTO de transacción se utilizará para transferir datos de transacción entre nuestros servicios. Vamos a agregarle los siguientes campos. En este punto, es posible que se esté preguntando cuál es la diferencia entre la tarifa real total y el total calculado v? Llegaremos a eso en breve. Ahora, vayamos al controlador de pestañas Enviar. Vamos a agregarle los siguientes campos. Estos campos se vincularán a las etiquetas correspondientes en la pestaña Enviar archivo FXML. Ahora vamos a implementar el método send. Primero. Convertiremos la cantidad a enviar texto en una cantidad decimal grande. Ahora, crearemos un objeto DTO de transacción usando el servicio create transaction que creará. Inyectemos este servicio en esta clase. Vamos a crearlo en el paquete de servicios GUI dots. Ahora, terminemos de inyectarlo en esta clase. Aquí llamaremos al método create en él, pasando la dirección para enviar texto y la variable amount. Vamos a crear este método. Ahora, usaremos este método para abrir la ventana de diálogo, pasando el DTO de transacción como su parámetro. Vamos a crearlo. Después de abrir la ventana de diálogo, llamaremos al método clear en la dirección a enviar y la cantidad a enviar variables para borrar el contenido en estas entradas. Ahora, vayamos al servicio de creación de transacciones. Vamos a agregarle la anotación de servicio. Implementaremos el método create. Ahora, la idea aquí es utilizar muchos de los servicios que hemos construido en los videos anteriores para crear una transacción y algunos datos adicionales para el DTO de transacción. Para eso, lo primero que haremos es utilizar el servicio de tarifa estimada para obtener la tasa de tarifa y almacenarla en la variable de tasa de tarifa. Entonces, vamos a inyectar este servicio en esta clase. Y llamemos al método de estimación en él. Ahora, obtendremos las direcciones de billetera cargadas actualmente usando el objeto wallet actual. Entonces vamos a inyectarlo en esta clase. Entonces llamaremos a las direcciones get como método de cadenas en él. A continuación, obtendremos todos nuestros UTXOS de cartera. Para eso, usaremos la lista de nodos cliente no gastado. Entonces vamos a inyectarlo en esta clase. Llamaremos al método list unused en él, pasando las direcciones y el nombre de la billetera actual como sus parámetros. Ahora, usaremos el selector de monedas para seleccionar los UTXOS que se utilizarán como entradas en nuestra transacción. Así que vamos a inyectar el selector de monedas en esta clase. Ahora, llamaremos al método select en él, pasando los UTXOS, la cantidad convertida en Satoshi la tasa de tarifa, la dirección a enviar y la dirección de cambio de billetera actual, llamando al billetera actual obtener el método de cambio de dirección, que creará. Así que vamos a crear este método. Simplemente devolverá la propiedad de cambio de dirección. Vamos a crear esta propiedad como una cadena. Vamos a moverlo hasta aquí. También vamos a crear un setter para ello. Lo usaremos más tarde. Ahora, usemos el servicio de creadores de transacciones para crear una transacción. Entonces, vamos a inyectar este servicio en esta clase. Llamemos al método create en él, pasándole los siguientes parámetros. Ahora que tenemos nuestra transacción construiremos datos adicionales para incluir en la transacción DTL. Siguiente. Primero, usemos el método de tarifa real total de la clase FI para obtener la tarifa real total pasará la transacción y los UTXOS seleccionados como sus parámetros. Vamos a crear este método. La diferencia entre los pies calculados totales y la tasa real total es que para este último, utilizamos la diferencia entre los montos de entradas y salidas para calcularlo. Mientras que para el primero, estimamos utilizando el tamaño de la transacción y la tasa de comisión. En teoría, se espera que ambos valores sean los mismos, pero usemos por defecto los pies reales totales cuando sea posible, para garantizar que estamos mostrando usuario la transacción real tarifa y para que el usuario vea posibles errores de tres valores. Entonces aquí calcularemos las cantidades de entrada, algunas en Bitcoin usando la siguiente transformación de flujo. Mapearemos el flujo UTXOS seleccionado para producir un flujo de cantidades UTXOS. Luego usa el método reducido para sumar todos los valores en la corriente. Y usa el método or else para devolver cero si la cadena está vacía. Ahora, calculemos la salida entre algunos en Satoshi haremos la misma transformación que hemos hecho para las entradas, pero con las salidas de transacción esta vez. Ahora vamos a devolver la entrada algunos en BTC se convierte a Satoshi menos la salida algunos. Volver al servicio Crear transacción. Ahora, vamos a crear la variable F0 calculada total y asignarle el resultado de la llamada al método F0 calculado total. Esta vez, pasaremos la transacción y la tasa de comisión como sus parámetros. Ahora, calculemos el total gastado, que como su nombre indica, es la cantidad total en Satoshi's que el remitente gastó en esta transacción. Para ello, usemos el método total gastado pasando la transacción, como parámetros el método total gastado pasando la transacción, la tarifa total real y la dirección. Vamos a crear este método. Con esta declaración if. Verifiquemos si la dirección a enviar pertenece a nuestra billetera. Si no es así, devolveremos la tarifa real total más el monto de salida de la primera transacción. Si nuestra billetera lo contiene, eso significa que estamos transfiriendo bitcoins a nosotros mismos, y por lo tanto estamos gastando solo la tarifa de transacción. Finalmente, devolveremos un nuevo objeto DTO de transacción instanciado con estos parámetros, continuará implementando la función de ventana de diálogo en el siguiente video. Nos vemos. 54. 52 Enviar bitcoin parte 7 skillshare 2: En este video, terminaremos implementar la ventana de diálogo de transacciones. Entonces vamos al controlador de pestañas Enviar. En el método del diálogo abierto, instanciemos un nuevo objeto de diálogo como este. Entonces llamemos al método de propietario de la unidad en él, pasando el objeto window como su parámetro, así. Vamos a establecer el título del diálogo para enviar la transacción. Ahora con el siguiente código, definiremos que cuando hagamos clic en el botón Cerrar de la ventana de diálogo, la ventana de diálogo se cerrará. A continuación, crearemos un objeto cargador FXML dentro de un bloque try catch. Para instanciarlo será necesario inyectar el recurso FXML de diálogo en esta clase. Vamos a hacerlo. Agreguemos una anotación de valor a este campo indicando la ruta del diálogo de transacción sin FXML. Aquí llamaremos al método get URL en él. Entonces usaremos null en estos parámetros. Y el contexto obtiene la referencia del método de haz aquí. Primero, hagamos el contexto objeto de campo en esta clase y asignemos aquí. Ahora, estableceremos el contenido del dolor de diálogo al resultado de la llamada al método de carga del cargador FXML. Ahora con el siguiente código, obtendrá el controlador de diálogo de transacciones syn del cargador FXML. Vamos a crear este controlador en la clase de controladores. Finalmente, pasaremos el objeto DTO de transacción al controlador de diálogo de transacción sin usando el método de transacción set. Vamos a crear este método. Aquí, atraparemos una IOException que el cargador FXML puede lanzar y envolverla en una nueva excepción de tiempo de ejecución. Después mostraremos el diálogo usando este método. Ahora, antes de implementar el segundo controlador de diálogo de transacciones, vamos a ir a la actualización actual del servicio de monedero. Cuando actualicemos la cartera actual, debemos establecer su dirección de cambio, que se utilizará cuando enviemos una transacción. Entonces hagámoslo. Lo haremos obteniendo la segunda clave pública extendida de la billetera creada. Recuerde que esta clave extendida se derivó para generar direcciones de cambio. Entonces obtendremos su primera dirección y la configuraremos como la dirección de cambio de billetera actual. Ahora, vayamos al segundo controlador de diálogo de transacciones. Vamos a establecer la anotación Componente en él. Ahora, vamos al segundo diálogo de transacción FXML. Vamos a establecer el dolor de diálogo FX ID. Y vamos a establecer la propiedad del controlador FX a la ruta del controlador recientemente creada aquí. Ahora vamos a establecer cada etiqueta con un ID de ética en este archivo, este campo en el segundo controlador de diálogo de transacción mediante el uso de esta característica IDE genial. Ahora vamos a establecer cada campo aquí es privado. Agreguemos la anotación FXML por encima de todas ellas. Antes de implementar el método Set Transaction, vamos a crear el dominio de diálogo de transacción en el paquete de dominios. Pronto va a necesitar este registro. Modelará los campos que se mostrarán en el diálogo de transacción. Así que vamos a crear estos campos. Vamos a crear también esto a partir del método. Creará un nuevo diálogo de transacción a partir de un DTO de transacción. Usaremos el formato o método de formato Bitcoin para analizar correctamente el monto para enviar la tarifa real total y el total gastado también pasará la tasa de tarifa y la dirección de la transacción DTO a la instancia de diálogo de transacción. Volver al segundo controlador de diálogo de transacciones. En el método de transacción establecido, vamos a establecer el campo Transacción D TO en el DTO de Transacción Recibida. Vamos a crear este campo en esta clase. Ahora, vamos a crear el objeto de diálogo de transacción usando it's from method pasando el DTO de transacción como su parámetro. Luego estableceremos el monto a enviar texto al diálogo de transacción monto a enviar establecerá el texto del campo de tarifas totales al diálogo de transacción, tarifa total. El texto total del campo al diálogo de transacción suma el texto del campo de tasa de tarifa al diálogo de transacción. Tasa de comisión concatenada con la cadena BTC slash KV. Mordedura. Vamos a establecer la dirección para enviar los textos de campo a la dirección de diálogo de transacción a enviar. Ahora vamos a crear el método inicializado en esta clase. Aquí vinculará el botón de cancelar a una acción que cerrará la ventana de diálogo. Para ello, llamemos al método Lookup Button en el dolor de diálogo pasando el campo cancel a él. Después llamaremos a este método para agregar un controlador de eventos al botón cancelar. El manejador recibirá un evento de acción y un evento como sus parámetros. Y el cuerpo del controlador utilizará esta declaración para cerrar la ventana de diálogo. Ahora, vayamos a la prueba de enviar Bitcoin. Algo falta en esta prueba. Después de llamar al método send Bitcoin and wait, tenemos que instruir al nodo para que mine un bloque para que nuestro UTXO sea confirmado y pueda ser utilizado para crear una transacción. Para manejar eso, llamemos al método generate to address en el nodo generar para direccionar al cliente pasándole estos parámetros. Y vamos a mover esta línea de código a aquí. Ahora, vamos a ejecutar nuestro nodo. Y hagamos esta prueba. Como era de esperar, la prueba ha fallado, pero el diálogo de transacción se abrió y se llenó con datos de transacción. Ahora, vamos a mejorar esta prueba. Verificará si los valores en el diálogo de transacción son correctos. Pero primero, hagamos que esta prueba sea más resistente. Después de hacer clic en el botón enviar agregaremos código para asegurarnos de que esperamos a que aparezca el diálogo de transacción antes de actuar en la ventana de diálogo. Entonces, vamos a crear el método de peso para el diálogo. Aquí, llamaremos al peso para método. Pasando estos parámetros para esperar segundos de tiempo de espera en el cuerpo lambda obtendrá el dolor de diálogo y regresará solo después de que no sea nulo. Ahora, vamos a obtener el valor de cada etiqueta en el diálogo de transacción y almacenarlos en las siguientes variables. Agreguemos aquí el tipo de fila de transacción. Y cambiemos el nombre de la vista de tabla a tabla de transacciones. En el bloque entonces, agreguemos las siguientes aserciones para verificar si las etiquetas en el diálogo de transacción son correctas. Ahora, en el bloque where, agreguemos un caso de prueba para poblar las variables a las que acabamos de hacer referencia en el bloque de entonces. Aquí le falta un signo igual, igual. Vamos a arreglarlo. Agreguemos otro caso de prueba. Ahora, eliminemos estas líneas. Adaptará el código para crear transacciones previas acuerdo con la variable de número UTXOS anterior. Entonces para cada UTXO definido en esa variable buscará la dirección de recepción. Después llamaremos al método send Bitcoin and wait con estos parámetros. Ahora, sustituyamos el parámetro en la llamada al método correcto por la variable amount to send. Ahora, tenemos que asegurarnos de que la tasa de comisión sea igual a 0.0 002 para que funcione la prueba. Para ello, inyectaremos el servicio de tarifa estimada de nodo en esta clase y le agregaremos la anotación simulada de Bean. Después en el método de configuración, agreguemos el siguiente código. Se asegurará de que cuando se llame al método de estimación del servicio, entonces devolverá el valor de la tasa de tarifa que queremos. A este método de búsqueda del perímetro le falta la letra S al final. Se trata de honorarios totales. Ahora, hagamos la prueba. Se falla, pero por la razón equivocada, observe que la cantidad a enviar etiqueta está vacía. Eso es porque hay otra etiqueta con el mismo FX ID en el controlador de pestañas Enviar. También hay un campo de dirección para enviar con el mismo FX ID. Vamos al segundo controlador de diálogo de transacciones para arreglar eso. Cambiemos el nombre de este campo a la cantidad para enviar diálogo. Y cambiemos el nombre de la dirección para enviar campo a dirección para enviar diálogo. Vamos al diálogo de enviar transacción FXML para cambiar las etiquetas FX IDs. Bien, no tenemos que hacerlo, porque el IDE hizo ese trabajo por nosotros. Volver a la prueba de enviar Bitcoin. Actualicemos estos parámetros para buscar las etiquetas correctas. Ahora, hagamos nuestra prueba. Bien, las pruebas han fallado, pero sólo porque la tabla de transacciones no contiene el número esperado de transacciones. Eso significa que las etiquetas del diálogo de transacción son correctas. Genial. 55. Cómo funcionan las firmas de transacciones: En esta presentación, mostraremos cómo funcionan las firmas de transacción. Primero, revisemos los campos de una entrada de transacción. Las entradas de transacción tienen un campo de ID de transacción cuyo contenido indica de qué transacción proviene el UTXO que se está gastando en esa entrada. El campo de índice de salida indica qué UTXO de la transacción anterior está gastando la entrada. En conjunto, ambos campos hacen un punto de salida que indica inequívocamente qué UTXO, el insumo es el gasto. El campo ScriptSig está vacío para las entradas de transacción de segue contiene scripts de desbloqueo para entradas de transacciones no segue. Ese desbloqueo de scripts es una firma y una clave pública para transacciones comunes. Finalmente, la entrada de transacción contiene el campo de secuencia final. El campo de secuencia final define cuándo la entrada es válida para gastar. Este campo se ignora cuando su valor es igual al valor hexadecimal máximo para su tamaño. Para las entradas de transacción de segue, el contenido que para transacciones no Segway está en ScriptSIG se mueve al campo testigo. La firma en ese campo es una firma ECDSA obtenida utilizando la clave privada utilizada para derivar la dirección del UTXO. El insumo es el gasto. El otro campo en el testigo es la clave pública, que se deriva de la clave privada a la nos acabamos de referir. Pero espera, ¿qué es una firma ECDSA? Eddsa significa Algoritmo de firma digital de curva elíptica. Se trata de un algoritmo de firma que combina una clave privada y un mensaje para producir una firma. Y la firma ECDSA tiene una propiedad que permite verificar si es válida, es decir, verificar si una firma dada fue producida por una clave privada dada y un mensaje usando la clave pública derivado de esa clave privada, el mensaje y la firma. De esa manera, podemos verificar si una firma es válida sin revelar la clave privada utilizada para generarla. Puedes usar la ECDSA para firmar cualquier mensaje que quieras. En el caso de una firma de transacción, el mensaje que se firma es una versión modificada de la transacción serializada. Entonces veamos cómo se firman las transacciones de Bitcoin. Para firmar una transacción, hay que firmar cada entrada de transacción por separado. Para cada entrada de transacción comenzando con una transacción insana, que es una transacción donde sus entradas tienen script vacío, CIGS y testigos. Se crea un hash de firma, que es el hash de una versión modificada de la transacción serializada. Para ello, se utiliza un algoritmo hash de firma, que explicaremos en la siguiente diapositiva. El hash de firma será el mensaje a firmar con una clave privada válida para esa entrada y el hash de firma utilizará el ECDSA para generar la firma. Recuerde que la clave privada válida para una entrada es la misma clave privada utilizada para generar la dirección a partir del UTXO que la entrada está gastando. Si la entrada es una entrada de segmento, agregue la firma y la clave pública derivada de la clave privada referida al testigo. De lo contrario, agregue estos elementos al campo ScriptSig de entrada. Cuando los nodos reciben una transacción, verifican si las firmas de transacción son válidas. Para ello, utilizan el algoritmo de verificación de firmas citado en la diapositiva anterior. Lo hacen durante la ejecución del script como se explicó en la última presentación. Ahora, veamos cómo se genera el hash de firma. Existen diferentes algoritmos de hash de firma para entradas de transacciones segue, no segmento y raíz de tap. No obstante, los tres algoritmos modifican la transacción de alguna manera y producen un hash, que es el mensaje que se firmará. Veamos el algoritmo hash de firma para las entradas de un segmento. Para crear un hash de firma para una entrada de transacción dada, comience con una cadena vacía, luego agregue la versión de transacción a la cadena, concatene todos los puntos de salida de las entradas de transacción. Hash los resultados usando el algoritmo hash 256 agrega el hash resultante a la cadena, luego concatena todas las entradas y secuencias. Hash 256 el resultado, y agrega el hash a la cadena. Ahora agregue el punto fuera de la entrada que se está firmando a la cadena. Agrega la clave de pub script de los UTXOS gastados por la entrada que se firma a la cadena. Agrega la cantidad de UTXOS gastada por la entrada que se firma a la cadena. Agregue la secuencia final de la entrada que se firma a la cadena, concatene todas las salidas de transacción. Hash 256, el resultado, agrega el hash resultante a la cadena, agrega el tiempo de bloqueo de transacción a la cadena. Agregue el tipo de hash, que es sig hash all para transacciones comunes a la cadena. Hay otros tipos de hash, pero rara vez se usan. Definen las entradas y salidas. La entrada que se firma puede ir dentro de una transacción. Sig hash. Todo significa que la firma producida es válida solo en una transacción con todas las entradas y salidas de la transacción dada. Por último, hash 256, la cadena obtenida. El resultado es el hash de firma para la entrada que se está firmando. debe obtener un hash de firma para cada entrada de transacción que se firma. El proceso es replicado por nodos cuando verifican las firmas de transacción. 56. Cómo nuestra billetera y nuestro nodo manejarán las transacciones enviadas: Esta presentación explicará qué sucede cuando enviamos una transacción a un nodo Bitcoin. Luego veremos cómo nuestro monedero maneja actualmente las transacciones de recepción y cómo planeamos cambiarlo para calcular correctamente las direcciones de las transacciones y saldos totales de la billetera después de enviar una transacción. Entonces veamos cómo un nodo Bitcoin maneja las transacciones enviadas por nuestra billetera. Nuestro monedero enviará transacciones a nuestro nodo a través del método note RPC llamado send raw transactions. Nuestra aplicación enviará la transacción de señal en formato hexadecimal a nuestro nodo. Después de recibir la transacción, el nodo la valida. Si la validación pasa, el nodo difunde la transacción a otros nodos de la red Bitcoin. Los otros nodos hacen lo mismo hasta que todos los nodos de la red reconocieron la transacción. La transacción permanece en el mental por un tiempo, esperando que un menor la incluya en un bloque y minó el bloque con él. Finalmente, un menor transmite el bloqueo mental con la transacción a otros nodos de la red. A medida que los nodos reciben el bloqueo mental con la transacción, la transacción se excluye de la mental y se considera confirmada. Cada bloque agregado después del bloque con la transacción agrega una confirmación a la transacción. Se recomienda esperar seis conformaciones para que una transacción se considere irreversible. Ahora, veamos un modelo ingenuo de cómo nuestro monedero puede manejar las transacciones de envío. Después de que nuestro monedero envíe una transacción a nuestro nodo, el nodo enviará de vuelta a través de cero MQ, la misma transacción a nuestra aplicación. Nuestro servicio de tareas de nodo detectará la transacción y la enviará a nuestro oyente de transacciones recibidas. Como la mayoría de las transacciones tendrán un resultado de cambio, el oyente de transacciones recibidas generalmente verificará que la dirección de cambio es de nuestra billetera. Y usaremos el servicio UTXOS actualización para actualizar nuestras direcciones de billetera, transacciones y saldos, pero confiando solo en el oyente de transacciones recibidas como lo es actualmente para actualizar nuestro cartera va a plantear algunos problemas. En primer lugar, el cálculo del saldo del servicio UTXOS de actualización no considera los saldos de entrada. Por lo que tendremos que modificar la forma en que nuestro monedero calcula un vestido y saldos de transacciones para descontar los montos de entrada de los montos de cambio. Pero tendremos que lidiar con un problema mayor con este modelo. ¿Qué pasa con las transacciones sin cambio? En este caso, el oyente de transacción recibida no considerará que la transacción de recibo es nuestra ya que verifica solo las direcciones de salida y la salida de aroma no será de nuestra billetera. Por lo tanto, nuestra aplicación no se actualizaría. Está equilibrado para estos casos, adoptará la siguiente estrategia para superar estos problemas a la hora de actualizar nuestra billetera después del envío de transacciones. Después de enviar la transacción a nuestro nodo, publicaremos un evento de transacción enviada que será capturado por un oyente de transacción enviada. Entonces el oyente de envío de transacciones utilizará el servicio UTXOS de actualización para actualizar la billetera con la transacción para eliminar el tema de no actualizar transacciones sin cambios, tanto la transacción el oyente recibido y el oyente de recepción de bloque usarán un cliente de transacciones de lista de nodos para buscar todas las transacciones relacionadas con nuestra billetera en el nodo, este cliente enviará una lista de transacciones RPC llamar a nuestro nodo, que devolverá todas las transacciones relevantes al cliente. Después, utilizando las transacciones de devolución, el servicio de actualización UTXOS actualizará todas las transacciones en nuestra billetera y sus saldos correctamente. 57. 55 Enviar bitcoin parte 8 skillshare 2: En este video, construiremos algunas clases y servicios que nos permitirán firmar y enviar transacciones. Entonces primero, vamos a crear una clase llamada transactions signer service en el paquete api dot services. Agreguemos aquí la anotación de servicio. Ahora vamos a crear el método de signo aquí. Tomará un objeto de transacción en la semilla mnemotécnica, una contraseña y una lista de DTL UTXO que creará una clase. Así que vamos a crearlo en el paquete de dominios. Ahora, usaremos el método de rango de flujo para recorrer cada DTO UTXO. Para cada DTO UTXO, llamaremos al método sign pasando el parámetro a, que es el índice de la entrada a firmar, el DTO UTXO, que obtendrá usando el parámetro i, la transacción, la semilla mnemotécnica y la contraseña de la billetera. Vamos a crear este método. Cambiemos este nombre de parámetro a cadena semilla mnemotécnica para firmar una entrada de transacción. Primero tenemos que derivar la clave privada válida para desbloquear el UTXO que entrada está gastando. Si quieres recordar cómo se hace eso con mayor detalle, vuelve a ver las carteras HD y la presentación de las direcciones de Bitcoin. Entonces primero, vamos a crear una instancia de un objeto semilla mnemotécnico aquí, pasando la cadena semilla mnemotécnica y la instanciación. Ahora derivaremos una clave maestra usando el método mnemotécnico seed to master key ya que sus parámetros pasarán la contraseña. Y este prefijo. Para nuestro caso de uso, está bien pasar el prefijo privado de red principal incluso si lo usamos en otro entorno porque afecta solo a la serialización de la clave maestra, no al proceso de derivación. En el proceso de derivación de la clave maestra que al método de clave maestra primero deriva la semilla raíz, cual se menciona en la presentación anteriormente referida. Ahora, derivaremos la clave privada extendida usando el método CKD de clave maestra ya que su primer parámetro pasará la ruta de derivación UTXO DTO. Primero, vamos a crear este campo en el UTXO DTO. Y aprovechemos para sumar el campo de cantidad que necesitará a continuación. El siguiente parámetro será true, lo que indica que queremos derivar una clave privada extendida, una clave pública extendida. El último parámetro será el prefijo privado neto principal. Nuevamente, no hay problema en usar el prefijo de red principal aquí. Observe que la forma en que derivamos la clave privada extendida aquí es similar a cómo derivamos la clave pública extendida y el servicio de clave pública extendida. Usamos la misma ruta de derivación que hemos utilizado para crear la clave pública extendida para derivar la dirección UTXO para nuestra billetera. Ahora, obtendremos la clave privada deseada simplemente extrayéndola de la clave privada extendida a través del método de dos claves privadas. Este método está disponible en la siguiente versión Bitcoin Java. Entonces vayamos al archivo POM para actualizarlo. Ahora dentro de un bloque try catch, finalmente podemos usar el método sign de la clase de firmante de transacción ECDSA de Bitcoin Java. Este método tomará la transacción, la clave privada, el índice de entrada, la cantidad UTXO DTO convertida a Satoshi. Y el booleano true, que indica que esta entrada está segmentada. El mismo método obtendrá un hash de firma con la clave privada. Usaremos la ECDSA para obtener una firma para esa entrada. Después insertará la firma y la clave pública derivada de la clave privada pasada en el testigo de transacción. La cantidad UTXO es necesaria para el hash de firma, y el último parámetro true es necesario para la generación correcta del hash de firma y para agregar correctamente la firma y la clave pública al testigo en lugar de en el scriptSig, que es el caso de entradas que no son de segmento. Finalmente, capturamos una posible IOException que el método sign puede lanzar y envolverlo en una nueva excepción de tiempo de ejecución. Ahora, vamos a crear el nodo send raw transactions client en el paquete node dot client. Este servicio será necesario para enviar nuestras transacciones a nuestro nodo Bitcoin. Vamos a agregarle la anotación de servicio. Inyectemos el cliente de nodo en esta clase. Y vamos a crear el método send. Aceptará una cadena hexadecimal de transacción como su parámetro. Aquí llamaremos al cliente nodo make request método. Lo usaremos para llamar al método RPC del nodo Bitcoin de transacción en bruto de envío . Como de costumbre, pasemos un nuevo objeto de referencia de tipo parametrizado. Aquí. La URL está vacía, y pasaremos el parámetro hexadecimal de transacción como último parámetro. Ahora en el paquete de servicios GUI dots, vamos a crear el segundo servicio de transacción. Este servicio se encargará de firmar y enviar la transacción creativa. Después de hacer clic en el botón Enviar en el diálogo de transacción, agreguemos la anotación de servicio a esta clase. Y vamos a crear el método de firmar y enviar. Devolverá un futuro de tipo nulo. Y tomará como parámetros el DTO de la transacción y la contraseña del monedero. Ahora, primero crearemos una lista de UTXOS, CTO, convirtiendo los UTXOS seleccionados del DTO de transacción. Llamaremos al mapa de métodos en el flujo UTXOS seleccionado y usaremos el generador de DTO UTXO para construir el UTXO d t va desde cada objeto UTXO. Así que vamos a inyectar el constructor UTXO DTO en esta clase. Vamos a crearlo en el paquete de servicios punto GUI. Ahora, vamos a crear este método de compilación. Devolverá un DTO UTXO de regreso al servicio de transacciones del centro. Aquí devolverá el método list llamado en el stream resultante. Vamos a refactorizar aquí para usar la referencia del método en lugar de una lambda. Ahora, vamos a implementar este método. Primero. Agreguemos la anotación de servicio a esta clase. Aquí obtendremos el objeto de dirección de monedero actual correspondiente a la dirección UTXO recibida. Entonces, primero inyectemos la billetera actual en esta clase. Ahora llamaremos al método get address en él, pasando la dirección UTXO como su parámetro. Vamos a crear este método. Devolverá un objeto address. Aquí devolverá el resultado de llamar al método get addressed en el campo addresses, pasando la dirección recibida como su parámetro. Finalmente, obtendremos el índice actual de direcciones de monedero y lo almacenaremos en la variable de índice de direcciones. Ahora, obtendremos la misma dirección de la cartera actual y obtendremos su tipo de dirección, almacenándola en la variable de tipo de dirección. Ahora, obtendremos la ruta de derivación UTXO llamando al método build derivation path con el tipo de dirección y el índice Address. Vamos a crear este método. Aquí. Usaremos el objeto address configs para obtener parte de la ruta de derivación. Así que vamos a inyectarlo en esta clase. En realidad, será una lista de configs de direcciones. Vamos a arreglarlo. Ahora desde el flujo de configuraciones de direcciones, usaremos el método de filtro para seleccionar la configuración de dirección válida para el tipo de dirección. Después usaremos el método find first y obtendremos la configuración de dirección que queramos. Finalmente, obtendremos la ruta de derivación de la configuración de la dirección y concatenaremos con la siguiente cadena. Añadiremos una barra diagonal hacia adelante y luego agregaremos el índice de direcciones. Aquí devolverá un nuevo DTO UTXO pasando la ruta de derivación y la cantidad UTXO. Volver al servicio de envío de transacciones. Aquí, necesitaremos el servicio de firmante de transacciones. Así que vamos a inyectarlo en esta clase. Ahora, llamaremos al mismo método en él ya que sus parámetros pasarán la transacción DTO de transacción, la semilla mnemotécnica de billetera actual. Entonces, vamos a inyectar la cartera actual en esta clase. Vamos a crear este método en la cartera actual. Devolverá una cadena. Aquí, devolverá el campo semillero mnemotécnico. Vamos a crear este campo. Y agreguemos un setter para este campo. El tercer parámetro de este método es la contraseña de la billetera. El siguiente parámetro son los CTO UTXO. Ahora, en un bloque try-catch usaremos el nodo send raw transactions client para enviar una transacción firmada a nuestro nodo. Así que vamos a inyectarlo en esta clase. Llamaremos al método send en él, pasando la transacción DTL transacción serializada usando el método serializado capturará una IOException y la envolverá en una nueva excepción de tiempo de ejecución. Ahora usaremos la aplicación Event Publisher. Así que vamos a inyectarlo en esta clase. Lo usaremos para publicar un nuevo evento de transacciones enviadas pasando esto y el DTO de transacción como sus parámetros. Así que vamos a crear el evento de transacción enviada en el paquete de eventos de punto GUI. Cambiemos el primer parámetro de firma del constructor para aceptar un objeto. Y pasemos este objeto al súper constructor. Y establecemos el campo DTO de transacción el DTO de transacción recibida. Agreguemos este campo a esta clase. Y vamos a crear un getter para ello. Usaremos este evento más tarde. Volver al método sign and send devolverá aquí un nuevo resultado asincrónico, pasando null como su parámetro. Vamos a agregar la anotación asíncrona a este método pasando el servicio ejecutor predeterminado como su parámetro. Recuerda que lo estamos haciendo para ejecutar este método de forma asincrónica, que es nuestra política a la hora de comunicarnos con nuestro nodo. Bien, hemos creado el campo semilla mnemotécnico en la clase de billetera actual, pero ahora tenemos que configurarlo después de crear una nueva billetera. Entonces vayamos al registro de billetera y agreguemos el campo semilla mnemotécnico a él. Ahora vamos al servicio create wallet y agreguemos aquí la cadena de semillas mnemotécnicas como último parámetro en la instanciación de wallet. Ahora en el servicio de billetera actual de actualización, fijemos la semilla mnemotécnica de billetera actual a la semilla mnemónica de billetera. Ahora vamos al segundo controlador de diálogo de transacciones. En el método inicializado, llamemos al método Lookup Button en el dolor de diálogo pasándole el botón Okay. Ahora agreguemos un manejador de eventos a este botón. El primer parámetro es un evento de acción, que define el clic en el botón Okay como la acción. El segundo parámetro es un método Lambda que toma un objeto de evento y llama al método de transacción sign and send. Así que vamos a crear este método. Aquí. Necesitaremos el segundo servicio de transacción. Así que vamos a inyectarlo en esta clase. Ahora, llamaremos al método sign and send en él, pasando el DTO de transacción y el texto de la contraseña de la billetera como sus parámetros. Finalmente, cerraremos el dolor de diálogo usando el método hide en la ventana del panel de diálogo. Vamos a ejecutar nuestro nodo. Y finalmente probemos lo que hemos hecho ejecutando la prueba de enviar Bitcoin. Genial, las pruebas han pasado. El monedero, detectó nuestra transacción y la agregó a la tabla de transacciones. Pero espera, hay algo extraño. Rebobinaré el video y lo pausaré en la vista de tabla de direcciones para verificar algo. Esta es la tabla de direcciones después de que nuestra billetera envió nuestra transacción en el primer caso de prueba, observe que la billetera detectó que una de nuestras direcciones de cambio en la segunda fila recibió Bitcoins. Bueno. Pero como la dirección en la primera fila tiene su UTXO en la entrada de la transacción que acabamos de enviar, su saldo actual debería ser cero porque se gastó su salida. Y dado que nuestra tabla de direcciones solo muestra que se viste con saldos mayores a cero, esta tabla solo debe mostrar una fila con la dirección de cambio. Ahora, revisemos la tabla de transacciones para el mismo caso de prueba. Boops, el saldo de la transacción que acabamos de enviar es incorrecto. Debe ser igual a -0.5 bitcoin menos la tarifa de transacción. El signo menos indicaría que hemos enviado una transacción desde nuestra billetera. El texto del saldo total también es incorrecto. Debe ser igual a 0.5 menos la tarifa de transacción. En el siguiente video, solucionaremos esos problemas. 58. 56 Enviar bitcoin parte 9 skillshare 2: En este video, arreglaremos algunos problemas que tuvimos en el último video. Uno de esos temas es que la tabla de direcciones muestra saldos obsoletos para direcciones cuya salida se gastó. Dado que la dirección gastada después de ser utilizada tiene un saldo cero, no debería aparecer en la tabla de direcciones. Entonces ajustemos esta prueba para verificar si la tabla de direcciones tiene solo una fila y si esa fila tiene un equilibrio igual al cambio esperado en Mount. Aquí, obtendremos la tabla de direcciones usando el método de búsqueda. Y en el bloque entonces comprobará si la tabla de direcciones tiene una fila. Comprobemos también si el saldo de la primera fila es igual a esta variable, que definiremos en el bloque web. A continuación, definamos la cantidad de cambio en las cajas de desgaste negro. Otro problema que hemos visto en el último video es que el saldo de la transacción es incorrecto en la tabla de transacciones. Eso está sucediendo porque cuando nuestra aplicación recibe una transacción de nuestro nodo, está considerando solo el saldo de cambio como saldo transacción para asegurar que la prueba detecte este error, agreguemos la siguiente línea y luego block comprobará si la primera fila de la tabla de transacciones tiene un balance igual a menos la variable total gastada. El saldo también es incorrecto ya que es igual a la suma de todos los saldos de transacciones. Entonces hagamos que nuestra prueba detecte este problema. Aquí. Comprobaremos si el texto del saldo total es correcto. Primero, definamos esta variable. Será igual al texto presente en la etiqueta de saldo total de la ventana después de enviar una transacción. Comprobemos si esta variable es igual al siguiente texto. Y aquí definamos la variable funds y actualizada en el stream final lambda. Ahora, vamos a ejecutar nuestro nodo. Y hagamos esta prueba. Bien, La prueba ha fallado porque la tabla de direcciones tiene dos filas. Arreglemos esos problemas. Para ello, vamos a crear el oyente de transacciones enviadas. Pero primero, arreglemos algo totalmente ajeno. El bloque de escucha recibido está en el paquete de eventos de punto de nodo en lugar del paquete de oyentes de punto de nodo. Vamos a arreglar eso. Con eso fuera del camino, vamos a crear un oyente de envío de transacciones en el paquete de escucha de puntos GUI. Como su nombre indica, este oyente manejará el evento de transacción enviada que el servicio de transacción publicará después de enviar una transacción. Vamos a agregarle la anotación de componente. Se implementará el listener de aplicación con el tipo de evento de transacciones enviadas. Vamos a implementar su método. Aquí liderará la actualización del servicio UTXOS. Así que vamos a inyectarlo en esta clase. Ahora, llamemos al método de actualización pasando la transacción de evento DTO. Ahora vamos a crear este método. Aquí obtendremos una lista de UTXOS a partir de la transacción DTO UTXOS seleccionada. Usaremos un mapa en la transmisión UTXOS seleccionada e instanciaremos un nuevo UTXO para cada UTXO recibido, pasará cada campo UTXO en la instancia UTXO, excepto la cantidad que será cero ya que acabamos de gastarlo. Ahora para actualizar nuestras direcciones de billetera, llamaremos al método de actualización del servicio de actualización de direcciones de billetera actuales , pasándole los UTXOS. Y para actualizar las transacciones del monedero, llamemos al método de actualización en el servicio de transacciones Update Current Wallet pasará el resultado de llamar a la fila de transacciones del método a misma con el DTO de transacción como su parámetro. Por último, llamemos al método de actualización del servicio balanceado de billetera actual método de actualización del servicio balanceado para actualizar el saldo actual de la billetera. Vamos a crear esto a partir del método en la clase de fila de transacción. Aquí devolverá una nueva fila de transacciones en un bloque try-catch. instanciaremos con el ID de transacción DTO de transacción. La transacción formateada DTO total gastada negada usando el método negate. Hará que el valor sea negativo ya que lo estamos gastando. Tendrá cero confirmaciones. Y su fecha será la fecha actual. Finalmente, capturaremos una IOException que puede ser lanzada por el método de ID de transacción y rápida en una nueva excepción de tiempo de ejecución. Volver al servicio Actualizar UTXOS. Ahora vamos a crear el método de actualización que recibirá una fila de transacción en la actualización actual El servicio de transacciones Wallet utilizará el método de ejecución posterior de la plataforma ya que el siguiente código modificar la interfaz del monedero. Aquí pasaremos una lambda que llamará al método add transactions row en la billetera actual pasará el camino de transacción a este método. Ahora, vamos a crear este método. Movamos este método a esta ubicación cerca del método add transactions rows. Aquí llamaremos al método add transactions row en el campo de filas de transacción, pasando la fila de transacción como su parámetro. Vamos a crear este método en la clase de filas de transacción. Aquí, pondremos la transacción escrita en la hoja de ruta de la transacción usando el ID de fila de transacción como clave. Bien, con estas modificaciones, esperamos que al menos se actualice la tabla de direcciones. Volvamos a ejecutar la prueba de enviar Bitcoin para verificar eso. Bien, Las direcciones presentadas ahora son correctas, pero la prueba falló debido a la tabla de transacciones. Las transacciones de envío aún están con un saldo desactualizado. Eso sucedió porque aunque nuestro oyente de transacciones sin está actualizando la transacción correctamente, cuando nuestra billetera recibe la misma transacción de nuestro nodo, detecta una actualización es solo el cambio de dirección UTXO. No descuenta la cuota y el insumo que hemos gastado. Debemos cambiar la forma en que actualizamos nuestras transacciones actuales de billetera para solucionarlo. En el método de actualización del servicio UTXOS, que se llama después de que nuestra aplicación reciba una transacción, llamará al nodo RPC lista de transacciones método. Este método devolverá todas nuestras transacciones de billetera, incluidas las que le enviamos lo suficientemente inteligentes como para devolver transacciones con saldos negativos si se envían desde nuestra billetera. Con estas transacciones en mano, podemos actualizarlas correctamente en nuestra aplicación. Así que usemos la lista de nodos de transacciones cliente para obtener todas las transacciones de nuestro monedero y almacenarlas en la variable de transacciones de nodo. Inyectemos este servicio en esta clase. Y vamos a crearlo en el paquete api dot services dot no dot client. Terminemos de inyectarlo en esta clase. Ahora, hagamos el registro de transacción de nodo, que modelará el retorno del método de transacciones de lista, lo creará en el paquete de dominio y nodo de inicio. Aquí llamaremos al método de transacciones de lista, pasando el nombre de la billetera actual. Construyamos este método. Y agreguemos aquí la anotación de servicio. Inyectemos el cliente de nodo en esta clase. Aquí obtendremos una matriz de tipo node transactions llamando al método make request client node con los siguientes parámetros. La cadena de transacción de lista, que es el nombre del método RPC del nodo, una nueva referencia de tipo parametrizada. La URL de la billetera concatenada con el nombre de la billetera. Y cadena de asterisco, que indica que queremos todas las transacciones de esa cartera. El valor máximo entero, lo que significa que queremos el número máximo de transacciones en la respuesta cero, lo que le dice al método que no queremos omitir ninguna transacción. Y cierto, lo que indica que queremos vigilar únicamente las transacciones incluidas en la respuesta. Ver solo las transacciones son transacciones. El nodo no tiene la clave privada para gastar. Esta opción tiene sentido porque nuestra billetera no pasa ninguna clave privada a nuestro nodo. Finalmente, devolvimos la matriz de transacciones convertida en una lista. Ahora vamos a crear los campos de registro de transacción de nodo agregarán solo los campos que usarán. Son el T XID, las confirmaciones, el monto, la dirección, que es la dirección a la que el remitente pretende enviar bitcoins, no la dirección de cambio. Y el tiempo, que es la marca de tiempo de la creación de la transacción. Volver al servicio Actualizar UTXOS. Llamaremos al método de transacciones del nodo de actualización en el servicio de transacciones Update Current Wallet. Como su parámetro pasará las transacciones del nodo. Vamos a crear este método. Aquí, obtendremos una lista de filas de transacciones de las no transacciones. Llamaremos al método de filtro en el flujo de transacciones del nodo. Como su parámetro pasará una lambda que tomará una transacción de nodo y verificará si la billetera actual contiene la dirección de transacción del nodo. Luego agregamos un operador o y verificamos si la billetera actual contiene una transacción con el ID de no transacción. Este filtro dará como resultado un flujo de transacciones que contiene solo las transacciones a las que se dirige enviar es una de las nuestras, que cubre las transacciones de recepción. La condición después de que el operador o realice el flujo de transacciones también incluye transacciones que nuestra aplicación ya tiene. Eso significa que las transacciones que anteriormente fueron agregadas por el oyente de envío de transacciones tendrán su balance correctamente actualizado con saldos negativos. Ahora, no vamos a la transmisión resultante usando el método de la fila de transacción. Vamos a crear este método y moverlo a aquí. Aquí devolverá una nueva fila de transacción instanciada con el ID de transacción del nodo. El monto de transacción de nodo formateado, las confirmaciones de transacción nodo y el tiempo de transacción de nodo convertido en una cadena. Ahora convertimos el flujo de transacciones en una lista. Por último, usamos el método platform run later y usando un lambda, llamamos a las filas de transacción Add en la billetera actual pasando las filas de transacción a la misma. Eliminemos este método ya que ya no lo necesitaremos. También eliminemos este método en la fila de transacciones por el mismo motivo. Una cosa más aquí en el método de filas de transacciones publicitarias en la clase de filas de transacciones, tenemos que actualizar el saldo de la fila de transacciones antes de que nuestros cambios surtan efecto. Entonces, vamos a incluir el siguiente código para hacer eso. Ahora, vayamos a la prueba de enviar Bitcoin. Antes de ejecutarlo, incluyamos la llamada dormida después de que la prueba haga clic en el botón OK en el segundo diálogo de transacción. Con eso, evitamos que la prueba falle debido a las condiciones de la carrera. Ahora, hagamos nuestra prueba. Genial, las pruebas han pasado. Ejecutemos todas las pruebas de aplicación para asegurarnos de que no hemos roto nada en nuestras billeteras. Voy a acelerar el video ahora, ya que estas pruebas tardarán algunos minutos en ejecutarse en la realidad. Genial. Todas las pruebas han pasado. 59. 57 Enviar bitcoin parte 10 skillshare 2: En este video, agregaremos más pruebas para verificar si nuestra billetera funciona como se esperaba al enviar transacciones en diferentes escenarios. Veamos si nuestro monedero puede enviar dos transacciones, una tras otra. Para ello, vamos a duplicar esta prueba en la clase de prueba de enviar Bitcoin. Cambiemos su nombre a. Debería enviar Bitcoin a tiempos. Arreglemos su formato. Cambiemos el nombre de la billetera a mi prueba mientras esté a las diez. Ahora vamos a extraer esta sección de código a un método. Lo llamaremos enviar Bitcoin. Vamos a sumar la cantidad a enviar como su segundo parámetro. Después de crear una transacción, dará clic en el botón Ok para enviarla. Entonces usaremos esta línea de código para hacer que nuestro nodo mine un bloque. Con esto, esperamos que nuestra segunda transacción sea confirmada, lo que nos permite utilizar el cambio UTXO generado por esa transacción como entrada en la siguiente transacción. Ahora haremos clic en la pestaña Enviar. Y llamaremos al método del sueño con estos parámetros para esperar a que se confirme nuestra transacción. Después de enviar la primera transacción, esperamos que nuestra primera dirección de cambio se muestre en la tabla de direcciones. Esperamos que se use una dirección de cambio diferente en la segunda transacción porque es importante no reutilizar las direcciones al recibir Bitcoins por razones de privacidad. Entonces compararemos la dirección de cambio en ambas transacciones y verificaremos si no son iguales. Para ello, busquemos la tabla de direcciones con esta línea de código. Cambiemos el tipo TableView a la fila de direcciones por razones de corrección. Eliminemos la declaración aquí, y aprovechemos para solucionar el mismo problema en el método de prueba anterior. Almacenará la primera dirección de cambio en esta variable, obtenerla de la tabla de direcciones. Después volveremos a llamar al método send Bitcoin para enviar la segunda transacción. Después de la segunda transacción volveremos a buscar la tabla de direcciones. Esperemos que la primera fila de la tabla contenga la segunda dirección de cambio. Entonces, volvamos a consultarlo y almacenar la dirección de la primera fila y la segunda variable de dirección de cambio. En el bloque entonces se agregará la siguiente aserción para verificar si la dirección del primer cambio no es igual a la segunda. Aquí, esperaremos que el tamaño de la tabla de transacciones sea igual al número UTXOS anterior más dos. Y cambiemos esta parte del texto del saldo total. Esperamos que el saldo confirmado sea igual a los fondos menos el total gastado. Vamos a quitar este caso de prueba, sólo tendrá un caso para esta prueba. Cambiemos la cantidad para enviar un 0.25. Actualicemos el total gastado en consecuencia. Y cambiemos los últimos cuatro dígitos de la cantidad de cambio. Esta cantidad de cambio es la suma de los montos de cambio de las dos transacciones. Ahora, vamos a ejecutar nuestro nodo. Agreguemos la anotación de ignorar a la primera prueba, ya que queremos ejecutar sólo la última prueba. Y vamos a ejecutarlo. La prueba ha fallado porque la primera dirección de cambio es igual a la segunda dirección de cambio. Arreglemos esto. Vamos a la actualización actual del servicio de direcciones de monedero moverá esta línea de código a esta ubicación. Aquí agregaremos una declaración if para verificar si la dirección que se está actualizando es una dirección de cambio. Agreguemos esta constante a esta clase. Será igual a dirección tipo seg cambiaría. En el cuerpo de la declaración if, establecerá la dirección de cambio de billetera actual a la siguiente dirección. Agreguemos también una declaración de retorno a este cuerpo de declaración if. Volvamos a ejecutar la prueba. Genial, La prueba ha pasado. Ahora, comenzaremos a implementar algún manejo de errores para situaciones las que las cosas no van bien cuando intentamos enviar transacciones, por ejemplo, qué debería suceder cuando usamos la contraseña de billetera incorrecta cuando intentando enviar una transacción. Cuando nuestro monedero envía una transacción con la contraseña incorrecta, esto hace que la transacción se construya con firmas no válidas. Cuando nuestro nodo lo recibe, intenta validar esa transacción. Como sus firmas están equivocadas, devolverá un mensaje de error y no retransmitirá la transacción a otros nodos. Actualmente, nuestra cartera no está manejando el error devuelto y fallará silenciosamente. Vamos a crear una solución para esta situación. Nuestro nodo devuelve un error después de recibir nuestra transacción, mostrará al usuario una alerta de error diciendo que la billetera no pudo enviar la transacción. Y y. Primero, vamos a crear una prueba para este escenario. En la clase de prueba de enviar Bitcoin. Duplicemos el primer método. Vamos a renombrarlo a no debería enviar Bitcoin con contraseña incorrecta. Y ajustemos su formato. Cambiemos también el nombre de la billetera a mi billetera de prueba 11. Aquí haremos clic en el campo de contraseña. Definamos una variable para esta contraseña. Vamos a configurarlo a mi contraseña de prueba y escribirlo en el campo de contraseña. Después de recibir Bitcoins, almacenemos el saldo formateado en la variable de fondos formateados. Como no vamos a tener éxito en el envío de una transacción, esperamos que el saldo final de nuestra billetera no cambie y siga siendo igual a esta variable. Ahora, sustituyamos esta sección de código con una llamada al método send Bitcoin. Después de que aparezca el diálogo de transacción, haremos clic en el campo de contraseña de la billetera. Y escribiremos la contraseña equivocada. Después de hacer clic en el botón Bien, esperamos que aparezca un mensaje de error. Definamos este mensaje de error y lo almacenemos en esta variable. Entonces, con este código, intentará almacenar el nodo con este mensaje en la variable de consulta de nodo. La alerta de error tendrá un botón Ok que intentará hacer clic. En el bloque entonces, comprobará si los textos de consulta de nodo son iguales al mensaje de error. También verificará si la dirección en la tabla de direcciones tiene un equilibrio igual a la variable de fondos formateados. Esperamos que el tamaño de la tabla de transacciones sea igual a uno, ya que no mostraremos la transacción fallida en la tabla. También cambiemos aquí el saldo esperado de la transacción para que sea igual a los fondos formateados. También esperamos que el saldo total y el saldo confirmado sean iguales a la variable de fondos formateados. El saldo esperado no confirmado debe ser igual a cero con ocho decimales. Eliminemos el segundo caso de prueba en el bloque where. Ahora vamos a implementar la función de alerta de error. En el segundo servicio de transacción. Agreguemos aquí una declaración catch para detectar un error interno del servidor. Este es el tipo de error que devolverá el nodo si algo sale mal cuando intentemos enviarle una transacción. Ahora, usaremos el registrador para registrar este error. Así que agreguemos el registrador a esta clase como un campo estático. instanciará usando el método logger factory get logger, pasando esta clase como su parámetro. Entonces llamaremos al método error en él, pasando el error get response body como llamada al método de cadena. Después devolvemos la llamada del método de error del manejador de errores del nodo que le pasa el error. Inyectemos el manejador de errores de nodo en esta clase. Vamos a crear esta clase en el paquete de servicios GUI dots. Terminemos de inyectarlo en esta clase. Vamos a crear este método en él. Devolverá un futuro de tipo error. Volviendo a la ubicación que lo llamará, vemos que el ID indica un error de tipo. Para solucionarlo, vamos a cambiar el tipo de retorno del signo y enviar método a futuro de tipo error. Pero primero, vamos a crear el registro de error en el paquete de nodos de punto de dominios. Vamos a copiar esta línea y pegarla aquí. Lo cambiaremos para importar esta clase de error que acabamos de crear. Si no hacemos eso, Java utilizará su clase de error incorporada. Ahora, cambiemos este parámetro de tipo a error. Pasemos también la línea de importación a esta clase. Vamos a agregarle una anotación de Servicio. Ahora, antes de continuar implementando la función, ejecutemos la última prueba para verificar el formato del mensaje de error que devuelve el nodo en los registros. Primero, agreguemos la anotación de ignorar a esta prueba. Por lo que sólo ejecutamos la última prueba. Aquí, vemos que el nodo volvió al mensaje JSON. La parte importante dice que el script falló y 0 p igual verificar la operación. Eso significa que el nodo falló debido a una firma incorrecta al ejecutar el script combinado para validar la transacción. Ahora que sabemos lo que devuelve el nodo a la aplicación cuando la contraseña de la billetera es incorrecta, mapeemos esta respuesta a la respuesta de contraseña incorrecta que queremos que vea el usuario. En el manejador de errores de nodo. Vamos a agregar un bloque try-catch convertirá el error recibido en un objeto envoltorio de error de nodo. Así que vamos a crear este registro en el paquete de nodos de punto de dominios. Siguiendo la respuesta adyacente al error de nodo como la especificación agregará un campo de error de tipo de error de nodo aquí. Así que vamos a crear el registro de error de nodo en el paquete de nodos de punto de dominios. Tendrá un campo de código y un campo de mensaje. De vuelta al controlador de errores del nodo necesitará el asignador de objetos. Entonces vamos a inyectarlo en esta clase. Ahora, llamaremos al método read value en el mapeador de objetos ya que sus parámetros pasarán el error get response body como llamada al método string. Y la clase envolvedora de errores de nodo. Este código convertirá el error recibido en un objeto envoltorio de error de nodo. Finalmente, devolveremos un nuevo objeto de resultado asíncrono instanciado con un objeto de error. Para crear una instancia del objeto error, usaremos el error from method pasando el error node error wrapper error como su parámetro. Vamos a crear el método front. Devolverá un objeto de error. Agreguemos el campo de mensaje a este registro. El método front devolverá un nuevo objeto de error instanciado con un mensaje de error. Para crear el mensaje de error, agreguemos el campo de mensajes de error en esta clase. Este campo se encargará de mapear los mensajes de error del nodo a los mensajes que queremos mostrar. Será un mapa de claves de cadena y valores de cadena. Usemos el mapa del método para crearlo. Su primera clave será el mensaje de error devuelto por el nodo, que vimos en los registros de la aplicación anteriormente. El valor será el mensaje de error que queremos mostrar. Para ello, usaremos la contraseña incorrecta constante de la clase de mensajes de error que vamos a crear. Así que vamos a crear esta clase en el paquete de nodos de punto de dominios. Y agreguemos esta constante con el mensaje que queremos mostrar. Ahora, llamaremos al método Get o default en el campo de mensajes de error en el método form, su primer parámetro será el mensaje de error. Su segundo parámetro será un mensaje predeterminado, que definiremos en esta constante. Entonces, si el nodo devuelve un mensaje de error que aún no hemos mapeado, el mensaje de error que se muestra será un error ocurrido. Volver al manejador de errores del nodo. Agreguemos aquí una declaración catch para capturar la excepción de procesamiento adyacente que el mapeador de objetos puede lanzar. Después lo envolvemos en una excepción de tiempo de ejecución y lo lanzamos. Ahora vamos al segundo controlador de diálogo de transacciones. Aquí, obtendremos el resultado del método sign and send y lo almacenaremos en una variable. Solo asegúrate de importar la clase de error correcta. Ahora, necesitaremos el servicio de error de alerta. Entonces vamos a inyectarlo en esta clase. Este servicio se encargará de mostrar una alerta con un mensaje de error. Vamos a crearlo en el paquete de servicios GUI dots. Y terminemos de inyectarlo en esta clase. Ahora, llamemos al método handle error en el error de alerta o al objeto de servicio pasándole el resultado. Vamos a crear este método. Primero. Agreguemos la anotación de servicio a esta clase. Aquí declararemos un objeto de error. Entonces en un bloque try-catch se establecerá la variable de error a la llamada al método result dot get. Entonces atraparemos una excepción que el resultado puede arrojar y envolverlo en una nueva excepción de tiempo de ejecución. Ahora bien, en esta sentencia if comprobará si el error no es igual nulo. Si no lo es, entonces llamaremos al método alert error, pasándole el mensaje de error. Vamos a crear este método. Aquí. Crearemos un nuevo objeto de alerta con un error de tipo alerta. Después estableceremos el título de la alerta en error. Y estableceremos el texto del encabezado de alerta a error o dos. Vamos a establecer el texto del contenido de alerta en la variable de mensaje. Por último, llamemos al método show en el objeto alert. Ahora, volvamos a ejecutar la prueba. Genial, La prueba ha pasado. 60. 58 Enviar parte de bitcoin 11 Skillshare 2: En este video, seguiremos agregando más validaciones y alertas para notificar al usuario de intentos fallidos de transferencia. Primero, crearemos algunos casos de prueba para esos escenarios. Así que vamos a duplicar esta prueba agregará una prueba para el escenario donde el usuario quiera enviar una transacción con más bitcoins que sus fondos. Vamos a renombrarlo a no debería enviar Bitcoin sin fondos mayores a cantidad más v. Vamos a reformatearlo. Y cambiemos el nombre de la billetera a mi prueba mientras esté a las 12. Eliminemos estas líneas. Aquí. Vamos a establecer una variable de mensaje de error al contenido que queremos que el usuario vea por el error, el mensaje será no se pudo enviar transacción, no hay suficientes fondos. Después con este código, intentaremos almacenar el elemento UI con este mensaje en la variable de consulta de nodo. E intentaremos hacer clic en el botón Bien en el cuadro de diálogo de alerta. En el bloque entonces comprobaremos si el texto de consulta del nodo es igual al mensaje que definimos anteriormente. Eliminemos estas variables en el bloque where ya que no las necesitaremos. Y vamos a crear la variable cantidad anterior aquí con el siguiente valor. Duplicemos esta línea para crear un segundo caso de prueba. Este valor de cantidad será uno Satoshi inferior al necesario para enviar 0.5 bitcoin. Ahora, eliminemos esta línea. Sustituyamos estos valores con la variable de cantidad anterior. Ahora, crearemos un escenario de prueba similar, pero esta vez usando una billetera sin fondos. Entonces vamos a duplicar esta prueba. Cambiemos su nombre a no debería enviar Bitcoin sin ningún tipo de fondos. Cambiemos el nombre de la billetera a mi prueba mientras esté a los 13. Eliminemos estas líneas ya que no vamos a recibir ningún fondo. Y dejemos sólo el monto a enviar variable y el bloque where. Ahora implementemos la característica en la clase de servicio create transactions. Almacenemos el DTO de transacción en una variable aquí. Y vamos a devolver esta variable. Ahora. Antes de regresar, llamará al método de validar fondos, pasando el DTO de transacción como su parámetro. Vamos a crear este método. Utilizará este método para validar si la suma de los montos de entrada de transacción es mayor que la salida de la transacción entre algunos. Así que vamos a crear esta variable para almacenar la cantidad de entrada. Algunos le asignarán el resultado de llamar a la transacción DTO, le obtendrán cantidades de método de entrada. Vamos a crear este método. Aquí. Usaremos un mapa en la secuencia UTXOS seleccionada para crear una secuencia de cantidades UTXO. Entonces usaremos el método reducido para sumar cada cantidad obtenida. Finalmente, usaremos el método or else para devolver la suma o cero si no hay UTXOS disponibles. Ahora, vamos a crear las cantidades de salida get del método aquí. Usaremos una estrategia similar a algunas de las cantidades de salida. Pero en lugar de usar los UTXOS seleccionados, utilizará un mapa en el flujo de salida de la transacción. El método map devolverá los montos de salida convertidos a Bitcoin. Y usaremos el método reduce y un método Rails de la misma manera que lo hicimos para el método anterior. Volver al método de validar fondos. Aquí, crearemos la salida alguna variable para almacenar el resultado de llamar a las cantidades de salida get. Algún método que acabamos de crear. Ahora agregaremos una sentencia if para verificar si la suma de entrada es menor que la suma de salida más el total calculado F0. Si es así, lanzamos una nueva excepción de transacción de creación con el mensaje de no suficientes fondos. Vamos a crear esta constante en la clase de mensajes de error. Hagamos ambas constantes definitivas. Y vamos a crear la clase create transactions exception en el paquete de excepciones de punto GUI. Extenderá la excepción de tiempo de ejecución y pasará su mensaje al súper constructor. Aprovechemos para agregar otra validación aquí. ¿Y si tratamos de enviar una transacción sin una billetera cargada? Para manejar este caso, usemos esta declaración if para verificar si la billetera actual tiene alguna dirección. Si no es así, lanzamos una excepción de transacción de creación con un mensaje de billetera no cargada. Vamos a crear esta constante para almacenar este mensaje. Ahora, vamos al controlador de pestañas Enviar. Envolvamos la creación de DTL de transacción en un bloque try-catch. El método de diálogo abierto llamado a. Aquí, lo atraparemos. Crear excepción de transacción. Usaremos el error de alerta o servicio y el cuerpo de captura. Entonces vamos a inyectarlo en esta clase. Después llamaremos al método alert error, pasando el mensaje de excepción como su parámetro. Hagamos público este método. Vamos a la prueba de enviar Bitcoin. Agreguemos la anotación de ignorar a la prueba que hicimos en el último video. Vamos a ejecutar nuestro nodo. Antes de ejecutar la prueba, ajustemos algunos detalles. Agreguemos un punto al final de los mensajes de error. En el método send Bitcoin. Vamos a agregar este parámetro. Por defecto será true y solo llamará al método de diálogo wafer si es cierto. Ahora, pongámoslo en falso y estas llamadas, porque el diálogo de transacción no aparecerá en estas pruebas. Por último, hagamos las pruebas. Calificar las pruebas han pasado. Eliminemos todas las anotaciones de ignorar de esta clase. Ahora, agregaremos un montón de nuevas pruebas en una nueva clase llamada send Bitcoin test adicional en este paquete. Pero no te preocupes, esta vez simplemente copiaremos el contenido de esta clase desde la página Proyecto y Recursos. Todas estas pruebas deben pasar. Ojalá no tengamos que cambiar nada en nuestro código para ello. Pero ayudarán a garantizar nuestra billetera envíe las transacciones correctamente y detectará posibles rupturas de código que se harán en el futuro. Vamos a reformatear todos ellos. En la primera prueba verificaremos si una billetera con contraseña envía transacciones correctamente. La siguiente prueba generará transacciones sin necesidad de cambio y verificará si sus parámetros son correctos. Esta prueba intentará enviar una transacción a una dirección de nuestra propia billetera y verificar si la billetera calcula correctamente sus montos y saldos. Por último, la última prueba tendrá muchos casos de prueba diferentes con diferentes números de UTXOS anteriores y cantidades. Para que estas pruebas funcionen, movamos el método weight for dialogue en la prueba send Bitcoin a la clase de prueba GUI. Hagámoslo protegido. Eliminemos estas importaciones en la prueba de enviar Bitcoin. Una cosa más en el método send Bitcoin, en la prueba send Bitcoin, agreguemos aquí la súper palabra clave para asegurarnos llamaremos al método de peso correcto para diálogo, no al parámetro con el mismo nombre. Haremos otra prueba en esta clase. Esta vez, comprobaremos qué sucede cuando intentamos enviar una transacción con una cantidad de polvo. Entonces vamos a duplicar esta prueba. Cambiemos su nombre a no debería enviar polvo Bitcoin. Arreglemos su formato. Cambiemos su nombre de billetera a mi prueba mientras esté a los 18. Ahora, copiemos este código y lo agreguemos a nuestro método para financiar nuestra billetera. Cambiemos el mensaje de error a no se pudo enviar monto de la transacción para enviar es polvo. Cambiemos el bloque where, agregándole las siguientes variables. Escogeremos una cantidad a enviar igual a 293 Satoshi's, que sabemos que nuestro nodo no puede aceptar ya que se considerará polvo. Para la cantidad anterior elegirá 0.1 bitcoin. Dado que confiaremos en nuestra nota para detectar este tipo de error, esperaremos a que aparezca el diálogo de transacción después de hacer clic en el botón Enviar. Y agreguemos el click en la llamada al método del botón Okay para confirmar la transacción del diálogo. Ahora, vamos a la clase de error. Agreguemos la siguiente entrada al mapa de mensajes de error mapeará el error de mensaje de polvo recibido de nuestro nodo al mensaje presente en la constante de polvo en la clase de mensajes de error. Vamos a crear esta constante. Será igual al mensaje acabamos de definir en la prueba. Agreguemos la anotación de ignorar a las otras pruebas de esta clase y ejecutemos nuestra nueva prueba. Genial, La prueba ha pasado. Eliminemos todas las anotaciones de ignorar que agregamos anteriormente. En este punto, recomiendo ejecutar todas las pruebas de aplicación. Yo lo hice y todos pasaron. No lo voy a mostrar en este video porque tardaría varios minutos. Voy a dejar esto como ejercicio para el alumno. 61. 59 skillshare 2 de la parte 1 de Segwit: En este video, comenzaremos a refactorizar nuestra aplicación para prepararla, para agregar soporte para más tipos de direcciones. Será un refactor relativamente grande, pero veremos más adelante que nos permitirá agregar soporte para otros tipos de direcciones, como el seg anidado abordaría. La idea de este actor ref es centralizar todo lo específico de un tipo de dirección en un objeto de configuración de direcciones. Al hacerlo, podremos agregar más tipos de direcciones a nuestras billeteras agregando nuevos objetos de configuración de direcciones al proyecto. Después de hacer este refactor, agregaremos un nuevo tipo de dirección llamado segmento anidado, cuya importancia explicaremos en algunos videos. Entonces vayamos al registro de configuración de direcciones para agregar algunos campos. Añadiremos el campo generador de direcciones. Lo usaremos para definir el servicio utilizado para generar direcciones para diferentes tipos de direcciones. Un mapa con una clave de enumeración de entorno y un valor de cadena. Utilizaremos este campo para registrar los prefijos de dirección para cada entorno. Así que vamos a crear esto lo suficiente. En el paquete BYU w dot domains. Tendrá la red principal, la red prueba y las constantes de prueba reg. Agreguemos aquí el campo de prefijo ki extendido. Como su nombre indica, definirá el prefijo de la clave extendida que generará las direcciones. El siguiente campo será una cadena de predicado como parámetro type. Recibirá una función lambda con una dirección como parámetro y una expresión que devolverá true si la dirección coincide con el tipo de configuración de dirección y false. De lo contrario, agregaremos un campo de tipo de clave pub script para que podamos identificar qué configuración de dirección usar usando el tipo de clave pub script. Luego lo agregaremos por función con estos parámetros de tipo usaremos este campo para definir una función para analizar una dirección de un script dado, clave de pub y un prefijo. Ahora eliminemos el bean conflicto de direcciones para el cambio de dirección de Segway. En esta refactorización se utilizará solo un bean de configuración de direcciones tanto para el segmento las direcciones de cambio de segmento. Cambiemos la anotación Bean para reflejar este cambio. Ahora, cambiemos esta instanciación de configuración de dirección para incluir cada recurso relacionado con este tipo de dirección cambiará el campo de ruta de derivación a un mapa donde la clave será un tipo de dirección y el su ruta de derivación correspondiente. Aquí agregaremos dos entradas, una para el tipo de dirección de segmento y su ruta de derivación inicial, y la otra para el cambio de Segway y su ruta de derivación inicial. Ahora, como se aborda, generador agregará un nuevo generador de direcciones de segmento. Para el campo de prefijos de dirección se agregará el siguiente mapa se agregará una entrada para cada entorno y son prefijos de dirección P2, WP k h. El campo de prefijo ki extendido será la constante principal del prefijo neto segue. Como el emparejador de direcciones utilizará el comparador de direcciones es segue con la función Lambda. Así que vamos a crear esta clase y el paquete utils. Y vamos a crear esta función. Será una función que tomará una dirección y devolverá true si la dirección inicia con uno de estos tres prefijos presentes en las direcciones de segmento. El siguiente campo será igual al script P2 WP k h constante. Por último, el analizador de direcciones será una referencia al script P2 WP k h método de dirección. Volvamos a la configuración de la dirección para sustituir el tipo de ruta de derivación. Será un mapa con tipos de direcciones como claves y cadenas como valores. Ahora, vamos a crear la clase de buscador de configuración de direcciones en el paquete de servicios api dot usaremos este servicio como una forma de recuperar la dirección correcta puede falsificar y otros servicios que refaccionaremos a continuación. Entonces, vamos a agregarle la anotación de servicios. Y vamos a inyectar aquí una lista de configuraciones de direcciones. Ahora, vamos a crear este método que nos permitirá encontrar una configuración de dirección por dirección. Su tipo de retorno será opcional de tipo address config. Después filtraremos un flujo de configuraciones de direcciones y usaremos el comparador de direcciones de los config en el filtro lambda. Después devolvemos la configuración de dirección opcional correspondiente a la dirección recibida usando el primer método. Ahora vamos a crear otro método que devolverá un opcional de tipo address config. Esta vez, encontrará una configuración de dirección por su tipo de script. Será similar al método anterior, pero usaremos el filtro para verificar si la clave del script pub pasado coincide con la de la configuración de la dirección. También usaremos el primer método definido en este caso. Ahora crearemos un método para encontrar una configuración de dirección por tipo de dirección. Nuevamente, usaremos un filtro en una secuencia de configuraciones de direcciones. Esta vez, el filtro contendrá una lambda que verificará si el tipo de dirección config es igual al tipo de dirección anterior, o si es igual al cambio correspondiente tipo de dirección. Esta vez, devolveremos la dirección can fake sin el objeto opcional usando el método orals throw. Este método lanzará una excepción si no encuentra la configuración de dirección apropiada. Ahora estamos listos para comenzar a refactorizar otros servicios para usar nuestro nuevo buscador de configuración de direcciones y configuración de direcciones. Comencemos con el servicio create wallet. Eliminemos estas dos líneas. Aquí. Usaremos un FlatMap en la lista de configuración de direcciones. Después pasaremos un método lambda como su parámetro devolviendo en el cuerpo lambda la siguiente transformación obtendrá las rutas de derivación de la configuración de dirección recibida. Le falta una letra S final. Así que cambiemos el nombre de este campo a rutas de derivación. Ahora, obtendremos el conjunto de entrada de las rutas de derivación. Luego llamaremos al método map en el flujo de entradas de ruta de derivación que devolverá una clave de pub extendida para cada entrada usando el método de creación de servicio de clave de pub extendido. Como sus parámetros pasarán la clave maestra. El valor de entrada, que será la ruta de derivación, la clave de entrada, que será el tipo de dirección, y el prefijo ki extendido Address config. Por último, convertimos el resultado a una lista. Ahora vamos al servicio extendido de llaves de pub. Eliminemos estas líneas. Vamos a agregar un cuarto parámetro a este método. Será un prefijo ki extendido. Aquí, sustituiremos este argumento por el prefijo ki extendido, prefijo público. Ahora vamos al generador de direcciones de segmento. Aquí, agregaremos el prefijo como segundo argumento, y lo usaremos como parámetro aquí. Ahora, eliminemos la fábrica de prefijos de dirección de esta clase. Y agreguemos el segundo argumento a esta interfaz, generemos el método dos. Ahora vamos al generador secuencial de direcciones. En la llamada al método generate, usaremos la fábrica de prefijo de dirección. Entonces vamos a inyectarlo en esta clase. Ahora llamemos al método get en él, pasando el tipo de dirección recibida como su parámetro. Ahora refaccionaremos la fábrica de generadores de direcciones. Eliminemos todas estas líneas. Inyectemos el buscador de configuración de direcciones en esta clase. Aquí llamaremos al hallazgo por tipo de dirección en el buscador de configuración de direcciones, pasando el tipo de dirección como su parámetro. Después devolvemos el generador de direcciones de configuración de dirección telefónica. Ahora, refaccionemos la fábrica de prefijos de dirección. Eliminemos todas estas líneas. Entonces vamos a inyectar la dirección puede pensar Finder en esta clase. Nuevamente, encontraremos la configuración de la dirección por tipo de dirección usando este método. Después obtendremos los prefijos de dirección de la configuración de dirección encontrada. Por último, devolvemos el prefijo de dirección correspondiente al entorno actual de Bitcoin así. Arreglemos las pruebas para las clases que acabamos de refactorizar, comenzando con la prueba del generador secuencial de direcciones. Agreguemos el buscador de configuración de direcciones como campo en esta clase. Y vamos a asignarlo a un simulacro de esta clase aquí. Ahora, instanciemos una nueva configuración de dirección, configurándola en esta variable. Entonces usemos el método one para definir un objeto devuelto cuando llamamos al método find by address type en el buscador de configuración de direcciones. En este caso, devolverá la configuración de Segway. Entonces hagamos público este método en la clase de configuración de direcciones. Ahora cambiemos este parámetro de fábrica de prefijo de dirección a la cadena de red principal. Y pasemos el buscador de configuración de direcciones a la instanciación de la fábrica de generadores de direcciones. Hagamos esta prueba. Vaya, la compilación falló debido a un error en el constructor de DTO UTXO. Vamos a arreglarlo. Aquí. Obtendremos la configuración de la dirección usando el buscador de configuración de direcciones. Entonces vamos a inyectarlo en esta clase. Eliminemos la lista de configuración de direcciones de esta clase. Ahora, encontraremos la configuración de la dirección por tipo de dirección aquí. Entonces obtendremos la ruta de derivación usando el tipo de dirección recibida. Finalmente, concatenaremos la cadena slash y el índice de direcciones con el resultado. Volvamos a ejecutar la prueba. Genial, La prueba ha pasado. Ahora arreglemos la prueba del servicio de creación de billetera. Eliminemos estas líneas. Instanciará la configuración de la dirección aquí. Después crearemos aquí la lista de configuración de direcciones. Añadiendo el seg le configuraría. Eliminemos todas estas líneas. Ahora, instanciaremos los objetos necesarios como este. Hagamos esta prueba. Grado. La prueba ha pasado. Ahora arreglemos la prueba extendida de servicio de clave de pub. Añadiremos el prefijo main net seg como el último parámetro del método create. Y hagamos esta prueba. Genial, ha pasado. Por último, arreglemos la prueba del generador de direcciones de segmento. Eliminaremos la fábrica de prefijos de dirección de esta clase. Y pasaremos el prefijo de dirección principal net P2 WP k h como segundo parámetro a este método. Hagamos esta prueba. Grado. La prueba ha pasado. En el siguiente video, seguiremos refactorizando nuestra aplicación. 62. 60 skillshare 2 de Segwit anidado: En este video, seguiremos refactorizando nuestra aplicación. Entonces comencemos con la clase de analizador de direcciones. Inyectemos el buscador de configuración de direcciones en esta clase. Eliminemos este código. Ahora, usaremos el buscador de configuración de dirección para encontrar una configuración de dirección por tipo de clave pub script, pasando el tipo de clave pub script a este método. Después mapearemos el resultado y aplicaremos el analizador de dirección address config address, pasando como parámetros la clave pub script y el prefijo apropiado. Ahora, usaremos el método URL para devolver una cadena vacía si no se puede analizar una dirección. Regresemos esta transformación. Ahora, vayamos a la clase actual de monederos. Eliminemos la dirección de recepción y cambiemos la dirección de esta clase. En lugar de usar un campo para cada dirección de recepción y cambio, usaremos un campo de direcciones de recepción para modelar las diferentes direcciones que usaremos para recibir Bitcoins en nuestra billetera. Entonces agreguemos el campo de direcciones receptoras a esta clase. Será un mapa observable con tipos de direcciones como claves y cadenas como valores. instanciará aquí con un HashMap observable de la clase de colecciones FX. Eliminemos los métodos que utilizan los campos eliminados. Ahora vamos a crear el método set de direcciones receptoras. Pondremos una entrada en el mapa de direcciones de recepción para cada llave de pub extendida. La clave de cada entrada será un tipo de dirección obtenido utilizando el valor del método pasando como parámetro el tipo de clave pub extendida. El valor será la primera dirección de la llave de pub extendida. Ahora, vamos a crear el método set de dirección de recepción. Usaremos este método para actualizar la dirección de recepción actual para un tipo de dirección específico. Aceptará un índice de direcciones y un tipo de dirección como parámetros. Primero, obtendremos la siguiente dirección usando el método get address ID pasando estos parámetros. Después pondremos la dirección obtenida en las direcciones receptoras usando el tipo de dirección como clave. Vamos a crear el método get receive address. Tomará un tipo de dirección y devolverá la dirección de recepción actual para ese tipo la obtendrá de las direcciones receptoras usando el tipo de dirección como clave para la recuperación. Ahora, vamos a crear un getter para las direcciones receptoras. Cambiémosle el nombre para obtener direcciones receptoras observables. Ahora, vayamos al servicio de actualización de direcciones de billetera actual. Eliminemos todas estas líneas dentro de una plataforma ejecutada más tarde llamada. Agreguemos una función Lambda que utilizará la dirección de recepción del conjunto de billetera actual para establecer la siguiente dirección. Eliminemos estos campos ya que no los necesitaremos. Ahora, vamos a refactorizar la actualización actual del servicio de monedero. Eliminemos estas dos líneas. Entonces agreguemos una llamada al método set de direcciones receptoras que acabamos de crear en la billetera actual. Ahora, vamos al controlador de pestañas Recibir. Eliminemos este código. Aquí. Obtendremos las direcciones de recepción observables de la billetera actual y le agregaremos un oyente. El oyente será la siguiente función lambda. Con esta declaración if comprobará si la dirección receptora que se cambió fue una segue ¿qué dirección? Si es así, estableceremos el texto del campo de dirección de recepción en la dirección recién agregada. Ahora refactorizaremos cómo se usa la dirección de cambio en el proyecto. Así que vamos a crear una clase llamada tipo de cambio de dirección Finder. Esta clase será responsable de encontrar el tipo de dirección de cambio apropiado para una salida de dirección dada. Aunque podemos usar diferentes tipos de direcciones como salidas en una transacción, se recomienda usar el mismo tipo para complicar terceros al descubrir qué salida se utilizó como cambio. Este servicio nos permitirá atender esta preocupación. Agreguemos la anotación de servicio a esta clase. Inyectemos el buscador de configuración de direcciones en él. Ahora vamos a crear el método find. Este método devolverá un tipo de dirección y tomará una dirección como parámetro. Aquí llamaremos al método find by address en el buscador de configuración de direcciones. Luego mapearemos el valor obtenido al tipo de dirección de cambio equivalente usando el siguiente código. Por último, utilizamos el método o bien para devolver el seg cambiaría el tipo de dirección. Si no se encontró el tipo de dirección. Usaremos la dirección de cambio de Segway para este caso. Aunque permitiremos que nuestra aplicación envíe transacciones a la mayoría de los tipos de direcciones, necesitamos proporcionar este retroceso porque no implementaremos todos los tipos de direcciones como receptoras direcciones en nuestra cartera. Ahora, vayamos al servicio de creación de transacciones. Debemos refactorizar cómo se obtiene la dirección de cambio en esta clase. Agreguemos aquí la variable de cambio de dirección. Su valor será igual al resultado de la llamada al método de dirección de cambio fino con la dirección como parámetro. Así que vamos a crear este método. Primero sustituyamos estas llamadas de buen método de dirección de cambio por la nueva variable de dirección de cambio. Aquí obtendremos el tipo de dirección usando el buscador de tipo de dirección de cambio. Entonces vamos a inyectarlo en esta clase. Ahora, llamaremos al método find en el buscador de tipo de dirección de cambio, pasando la dirección como su parámetro. Después devolvemos una llamada al método get Receiver address, pasando como parámetro el tipo de dirección obtenido. Ahora, vamos a la clase de configuración de dirección. Añadiremos campos relacionados con la creación de la transacción. Ahora. El primero será el generador de entrada de transacciones con esta nueva clase como su tipo. Vamos a crear esta clase en el paquete de servicios API. Será una interfaz. método se llamará Build, devolverá una entrada de transacción y Su método se llamará Build, devolverá una entrada de transacción y tomará un UTXO como parámetro. Volver a la configuración de la dirección. Vamos a añadir el campo de entrada más tamaño de salida aquí. Lo usaremos más adelante en la clase de calculadora de polvo. También agreguemos aquí el campo ScriptSig size. Se utilizará en la calculadora de tamaño de transacción. Ahora, agreguemos también el campo firmante de transacciones. Vamos a crear esta clase en el paquete api dot services. Será una interfaz. Tendrá un método de signo el cual tendrá los siguientes parámetros. También lanzará una IOExcepción. Ahora en la clase de configuración de direcciones, definamos los nuevos campos en la configuración de dirección de segmento. Añadiremos un nuevo generador de entrada de segmento como generador de entrada de transacción. Vamos a crear esta clase en el paquete api dot services. Implementará la interfaz Builder de entrada de transacción , e implementará el método de compilación. Para implementarlo, copiemos el siguiente código dentro del método build inputs en la clase de creador de transacciones y peguémoslo aquí. Cambiemos este parámetro a un nuevo ArrayList. Almacenaremos esta entrada de transacción en esta variable. Entonces llamaremos al método set witness, pasando a un nuevo testigo con los mismos argumentos que hemos usado en el servicio de creadores de transacciones. Finalmente, devolvimos la entrada de la transacción. Vamos a copiar estas constantes y pegarlas al segue qué constructor de entrada. Y agreguemos aquí la anotación de servicio. Volver a la configuración de la dirección. Añadiremos 98 como entrada más tamaño de salida, cero como tamaño de ScriptSig y un nuevo firmante de transacciones Segway. Vamos a crear esta clase en el paquete api dot services. Implementemos el método del firmante de transacciones. Agreguemos aquí la anotación de servicio. Vamos al servicio de firmante de transacciones. Copiaremos esta línea y la pegaremos aquí. Sustituyamos este parámetro por la variable index. Y sustituyamos aquí el monto UTXO por la variable amount. Nuestra configuración de dirección finalmente está lista. Ahora vamos a la calculadora de tamaño de transacción. Usemos el comando IDE de código de limpieza para agregar la palabra clave final a cada campo de esta clase. Inyectemos el buscador de configuración de direcciones en esta clase. Eliminemos este código. Vamos a redefinir la variable all inputs mapeará el flujo de direcciones de entrada pasando una referencia al método de tamaño de entrada. Vamos a crear este método. Devolverá un double y tomará como parámetro una dirección. Aquí devolverá un código similar al anterior que define el tamaño de entrada. Pero el parámetro de tamaño ScriptSig se tomará encontrando la configuración de dirección adecuada. El uso del buscador de configuración de direcciones arrojará una excepción si no encontramos la configuración de dirección. Si lo encontramos, le quitaremos el tamaño de ScriptSig. Después le agregaremos la secuencia. Finalmente, sumaremos los resultados del tamaño de entrada usando el método de suma doble. Si no encontramos ninguna entrada, devolverá cero como la suma. Ahora, eliminemos estas líneas. Como el tamaño de entrada. Llamaremos al método map en el flujo de direcciones de salida usaremos el método de tamaño de salida para devolver cada tamaño de salida. Aquí devolveremos la suma del valor n, la longitud de la clave pub script y el resultado del método script pub key size pasando la dirección como parámetro. uso de una declaración if comprobará si la dirección es una dirección seg utilizaría el método Segway. Si lo es, entonces devolvemos la constante de la clave pub script. Si no lo es, lanzaremos la siguiente excepción. Recuerda que no usaremos la configuración de dirección para calcular el tamaño de salida porque la configuración de dirección se refiere solo a las direcciones que podemos aceptar en nuestras billeteras. Ya que planeamos soportar más direcciones de salida, entonces tomaremos como entradas, tendremos que manejar la construcción de salida sin usar la configuración de dirección. Finalmente, utilizamos el método reducido para calcular la suma de tamaños de salida. Y existe el método o else para devolver cero sin salidas. Eliminemos esta constante. Ahora. Vamos a la calculadora de polvo. Inyectemos el buscador de configuración de direcciones en esta clase. Agreguemos la dirección como segundo parámetro a este método de polvo. Vamos a eliminar esta línea, se creará la variable de tamaño de entrada más salida. Usaremos el buscador de configuración de direcciones para encontrar la configuración de la dirección por dirección. Si no se encuentra una configuración de dirección. Vamos a lanzar una excepción. Si lo es, entonces obtenemos su propiedad input plus output size y la almacenamos en una variable. Finalmente, devolvemos la fórmula para calcular si una salida es polvo usando la variable que acabamos de definir. Eliminemos esta constante de esta clase. Ahora, vamos a refactorizar el único selector de monedas de sorteo aleatorio agregará el parámetro de cambio de dirección a estos métodos. Y pasamos la dirección de cambio a la llamada del método de polvo. Vamos a refactorizar el servicio de creadores de transacciones. Ahora, eliminemos estas constantes. Inyectemos una lista de creadores de claves de pub script en esta clase. Vamos a crear esta clase en la ruta de los servicios api dot. Será una interfaz. Tendrá un método de coincidencia que devolverá un booleano y tomará como parámetro y dirección. Y tendrá un método de compilación que devolverá un script y tomará una dirección como parámetro. Terminemos de inyectar este campo a esta clase. También vamos a inyectar el buscador de configuración de direcciones en esta clase. Agreguemos la dirección de cambio a estas llamadas de método. Eliminemos este código de este método, crearemos la variable script y le asignaremos el resultado de la siguiente transformación de flujo. Se filtrará el script pub key builders stream para encontrar el que coincida con la variable address. Si no encontramos ninguna, lanzamos una excepción. Entonces llamamos al método build en el script pub key builder encontrado pasando la dirección como su parámetro. Finalmente, devolvemos la salida de la transacción que contiene la cantidad y la variable script. Ahora vamos a eliminar este método y usado de esta clase. En el método build inputs, eliminemos este código. Ahora, llamaremos al método map en el stream de UTXOS. En su interior pasará la siguiente lambda, encontrará la dirección config usando la dirección UTXO. Si no lo encontramos, lanzamos una excepción. Después obtenemos el generador de entrada de transacción desde la configuración de la dirección y lo llamamos método derramado, pasando el UTXO a él. Finalmente, usamos el método collect para convertir la secuencia resultante en una ArrayList. Vamos a crear la clase P2 WP k h script builder en el paquete api dot services. Se implementará la interfaz script pub key Builder. Implementemos los métodos de interfaz. Inyectemos la fábrica de prefijos de dirección en esta clase. En el método match devolverá el resultado de llamar a la dirección matcher es el método de prueba de Segway. En el método build, primero estableceremos la variable prefix en el prefijo address factory Get method call result pasará la constante Segway como su parámetro. Después devolvemos el resultado de la llamada al método de script P2 WP k h ya que el parámetro a este método pasará el resultado de llamar al método back 30 para decodificar al método hex. Primero, vayamos al archivo POM para actualizar la biblioteca Bitcoin Java a la versión 0.4, 0.4, que tiene el mejor método 32 que necesitamos. Pasaremos el prefijo y la dirección a este método. Ahora, vayamos a la clase de firmante de transacciones para más refactorización. Inyectemos el buscador de configuración de direcciones en esta clase. Eliminemos esta línea. En su lugar, llamará al mismo método pasándole estos parámetros. Vamos a crear este método creará la variable firmante de transacción. asignaremos el resultado de la siguiente transformación. Usaremos el buscador de configuración de dirección para encontrar una configuración de dirección por tipo de dirección pasará el tipo de dirección UTXO DTO a este método. Pero primero, agreguemos el campo de tipo de dirección al registro UTXO DTO. Y agreguemos el tipo de dirección a la instanciación de UTXO DTO en el generador de DTO UTXO. Volver al servicio de firmantes de transacciones obtendrá el firmante de transacción de configuración de dirección de la configuración de la dirección telefónica. Por último, llamemos al método de firma de firmantes de transacciones, pasándole estos parámetros. Agreguemos una cláusula throw a este método para indicar que este método puede lanzar una IOException. Se realiza la refactorización. Ahora arreglemos algunas pruebas, comenzando con la prueba del selector de monedas de un solo sorteo aleatorio. Agreguemos la configuración de la dirección al método de configuración. Entonces agreguemos la variable de lista de configuraciones de dirección con el segmento Config dentro de ella. Ahora instanciemos un nuevo buscador de configuración de direcciones, pasándole las configuraciones de direcciones. Ahora hagamos esta prueba. Genial, ha pasado. Ahora, arreglemos la prueba de servicio de creadores de transacciones. Al igual que la prueba anterior. Instanciemos una configuración de dirección y creemos una variable de configuración de direcciones y una variable de buscador de configuración de direcciones. También instanciemos un prefijo de dirección pasando la cadena de prueba reg y el buscador de configuración de direcciones a la misma. Ahora vamos a crear la variable script pub key builders le asignará una lista con un nuevo generador de scripts P2 WP k h dentro de él. Hagamos esta prueba. Genial, ha pasado. Ahora, arreglemos la prueba de la calculadora de tamaño de transacción. Al igual que las pruebas anteriores, instanciemos una configuración de dirección y creemos una variable de configuración de direcciones y una variable de buscador de configuración de direcciones. Cambiemos estas pruebas de caso. Pegaremos los casos de prueba que puedes encontrar en la página Proyecto y Recursos. Importemos el método de copias finales. Estos casos de prueba o iguales a los anteriores, pero tienen direcciones reales esta vez, ya que ahora son importantes para la lógica de la calculadora de tamaño de transacción. Hagamos esta prueba. Genial, ha pasado. Ahora, vayamos a la clase de prueba GUI. Agreguemos la constante principal del prefijo del segmento neto a esta llamada al método. Y agreguemos la constante reg test P2 WP k h address prefix constant como parámetro a esta llamada al método. Ahora te recomiendo que ejecutes todas las pruebas de aplicación. Todos deben pasar. 63. Dirigir las direcciones de Segwit: En esta presentación, hablaremos sobre las direcciones de segmentos anidados. Entonces, ¿qué es una segue anidada? ¿Qué dirección? Las direcciones de segmento anidadas también se conocen como segmento de rap P2, SSH dash p2, WPA y WPA2. Y direcciones P2 SSH. Este último nombre describe mejor lo que son y dirección que codifica un script hash de clave de pub pay to witness. Dentro de un script hash de pago a script. La mayoría de las billeteras modernas admiten estas direcciones. Su principal ventaja es que permiten que las billeteras más antiguas, que generalmente admiten direcciones hash de pago a script, pero no admiten direcciones de segmento nativas para enviarles bitcoins. Por lo tanto, los propietarios de direcciones de segmento anidadas pueden beneficiarse de algunas ventajas de las transacciones Segway, como tarifas de transacción más baratas y recibir fondos de billeteras antiguas. Entonces, ¿por qué la necesidad de segue direcciones nativas? Usted puede preguntar. La razón es que las direcciones nativas de segue hacen transacciones incluso más pequeñas que las direcciones de segmento anidadas. Las direcciones de segmento anidadas estuvieron disponibles en 2017 después de que la seg se actualizara, las reglas para generar direcciones de segmento anidadas se definieron en BIP 141. Hemos elegido direcciones de segmento anidadas como direcciones de recepción secundarias de nuestras billeteras para permitir recibir Bitcoins de billeteras antiguas. Entonces, para entender las direcciones de segmento anidadas, primero entendamos las direcciones P2 SSH. P2 SSH es un acrónimo de hash de pago a script. Las direcciones P2 SSH son exactamente eso. Codifican un hash generado a partir de un script de Bitcoin. Veamos el proceso para generar un tocado P2 SH. Comenzamos con un script de redimir serializado hexadecimal. Voy a canjear script suele ser un script de Bitcoin multi-firma, pero puede ser cualquier otro script Bitcoin. Utilizamos el algoritmo hash 160 para generar un hash de script a partir del script redeem serializado. Luego combinamos el hash de script con un prefijo y aplicamos el algoritmo de codificación base 58 para producir una dirección P2 SH a través de la decodificación base 58, podemos obtener el hash de script back a partir de una P 2 dirección SSH, una segue anidada. Qué dirección es simplemente una base 58 codificada P2 SSH script fue redimir script es un script de segmento. Ahora aprendamos a construir una clave de pub de script P2 SH. Recuerde que una clave de pub script es parte de una salida de transacción y es como la dirección de recepción está presente en una transacción. Entonces, comenzando con una dirección P2 SSH, primero basamos 58 decodificamos para obtener un hash de script. Luego construimos un script que consiste en un código de operación OP hash 160, el hash de script y un opcode OP igual. Esta es la clave de pub del script P2 SH. Para enviar fondos a una dirección P2 SSH, debes poner este script en la salida de la transacción junto con la cantidad de cualquier monedero, pero puedes enviar bitcoins a una dirección P2 SSH, puedes enviar bitcoins a una segue anidada. ¿Qué dirección? Ahora, veamos cómo construir una entrada de transacción de segue anidada, comenzando con la clave de pub válida para una dirección UTXO. Luego aplicamos el algoritmo hash 160 para obtener un hash de clave de pub. Combinando el hash con un prefijo cero, obtenemos un script de segmento. Este es el script de redimir, lo agregará a la entrada de transacción más adelante. Ahora firmará una transacción. Para hacer eso, primero producimos un hash de firma a partir de una transacción privilegiada usando el mismo algoritmo de hash de firma que usamos para firmar una transacción segue. Después combinamos el hash de firma con una clave privada válida para generar la firma usando el ECDSA. A continuación, mostramos la entrada de transacción de signo, el índice de salida de ID de transacción y luego los campos de secuencia funcionan la misma manera que otros tipos de transacciones. Agregamos el guión redimir en el campo ScriptSiG, y agregamos la firma y la clave del pub al campo testigo. Observe que a diferencia de las entradas nativas de seg, el ScriptSig no está vacío. En este caso. El campo testigo de las entradas de segmento anidadas tiene los mismos elementos que las entradas de segmento nativas. Ahora veamos cómo se ejecuta un script de segmento anidado durante la validación de transacciones por los nodos. validación de segmentos anidados requiere la validación de dos scripts combinados. Dada una clave de pub de script P2 SSH de algún UTXO y el correspondiente scriptSig de una entrada de transacción. Ambos guiones se combinan, formando el primer guión combinado. El script redeem, se pasa al script combinado como un solo elemento serializado. En esta primera validación, de izquierda a derecha, se evalúa cada elemento del script combinado, comenzando por el script redeem, que se agrega a la pila de ejecución. Después el hash OP 160, aplica el hash 160 y el script redeem, transformándolo en un hash de script. Luego se agrega el hash de script y el script combinado a la pila de ejecución. Finalmente, el código de operación igual OP compara ambos hashes de script y devuelve true si son iguales. Si no son iguales, la transacción se considera inválida. A continuación, se forma un segundo guión combinando el testigo y el guiónSiG. Esta vez, el guión redimir en el scriptSiG se evalúa en su totalidad tal como lo es en evaluaciones de guiones nativos de segue. Y al igual que la evaluación del script nativo de segue, el dígito cero inicial en el scriptSig desencadena una regla especial que lo convierte el script presente en el script combinado. A partir de ahora, el script combinado se ejecuta igual que el script combinado de las transacciones nativas del segmento. A partir del script combinado, las claves de firma y pub se agregan a una pila de ejecución. Entonces el opcode OPT up duplica la clave pub en la pila de ejecución. Hasta hash 160 hashes, la última clave de pub agregada a la pila. Luego, desde el script combinado, se agrega el hash de la clave de pub a la pila. Up equal verify opcode elimina los dos últimos elementos de la pila de ejecución y los compara. Si son iguales, el script continúa ejecutándose. Finalmente, el opcode sig objeto comprueba si la firma es válida para la clave pub que queda en la pila. Si es válido, devuelve true a la pila de ejecución. Después de agregar todos los elementos del script a la pila de ejecución, la entrada de transacción se considera válida si el último elemento agregado es verdadero, este proceso debe repetirse para cada entrada de transacción, todas sus entradas deben ser válidas para que una transacción se considere válida. Así como un recordatorio visual, repasemos de dónde cada elemento en la clave de pub script, vino cada elemento en la clave de pub script, ScriptSig y testigo durante la construcción de la transacción. El hash de script presente en la clave pub script vino de la base 58, decodificando la dirección del UTXO que se está gastando. El hash de la clave pub y el ScriptSig provenían del hash 160s de una clave pública válida. La misma clave pública está presente en el testigo. El testigo es firma vino aplicando el algoritmo ECDSA, cual necesita una clave privada válida. La clave pública y el testigo procedían de la clave pública derivada de la mencionada clave privada. Ahora, veamos algunos parámetros importantes para derivar direcciones de segmento anidadas. En la red principal de Bitcoin, el prefijo necesario para derivar las direcciones P2 SSH es C4. Después de que la base 58 codificara un vestidos con ese prefijo comience con el dígito tres en la red de prueba de Bitcoin y la prueba reg, el prefijo necesario para derivar las direcciones P2 SSH es 05. Después de la codificación base 58 direcciones con ese prefijo comienzan con el dígito a. La ruta de derivación utilizada para derivar direcciones de segmento anidadas comienza con la ruta 49 endurecida para billeteras, siguiendo las pautas BIP 49. 64. 62 skillshare 2 de la parte 3 de Segwit: En este video, implementaremos la dirección de seg anidada en nuestra billetera, agregaremos como otra opción para recibir Bitcoins en nuestra billetera. Primero preparemos nuestra aplicación para agregar algunas pruebas relacionadas con el nuevo tipo de dirección. Entonces vayamos al Nodo, consigamos nuevo cliente de dirección. Necesitamos que nuestra aplicación pueda llamar a nuestro nodo para generar direcciones P2 SSH. Así podremos crear pruebas para enviar Bitcoin a estas direcciones. Entonces usemos la opción de cambio de firma IDE para agregar un nuevo parámetro a este método. El nuevo parámetro será una cadena, su nombre será direccionado tipo, y su valor predeterminado será la cadena atrás 32. Agreguemos una cadena vacía a esta llamada al método. Este parámetro se usa si queremos agregar una etiqueta a nuestra nueva dirección, ya que no la necesitaremos, la configuraremos en una cadena vacía. Y agreguemos el tipo de dirección como último parámetro. Bien, ahora podemos pedirle a nuestro nodo que cree direcciones P2 SH si el refactor IDE funcionó. Ahora las llamadas actuales a este método tendrán la cadena hacia atrás 32 ya que son menos parámetros. Ahora, vayamos a la prueba de enviar Bitcoin. Movamos este método a la clase de prueba GUI. Hagámoslo protegido. En lugar de usar la palabra clave super aquí, usemos esto. Ahora, vayamos a la clase de prueba recibir Bitcoin. Copiemos todo el código de esta clase. En el paquete de prueba GUI. Vamos a crear una nueva clase de prueba llamada receive Bitcoin anidado segue test. Y peguemos el contenido a esta clase. Hagamos algunos ajustes a esta clase. Cambiemos el nombre de la clase para recibir la prueba de segue anidada de Bitcoin. Ahora cambiemos los nombres de los métodos de prueba. Agreguemos aquí una dirección de segmento anidada. Hagamos lo mismo con todos los demás métodos de prueba indicando en sus nombres que recibirán Bitcoins en segue anidado ¿qué direcciones? Ahora, ajustemos esta primera prueba. Ajustaremos el nombre de su billetera. Entonces modifiquemos aquí el parámetro de búsqueda. Entonces la variable address se asigna al valor del campo donde se dirige el segmento anidado. Aquí, en lugar de usar el método address is valid, usaremos el segmento anidado address is valid method we will create. Arreglemos este formato de código. Ahora, vamos a crear el segue anidado qué dirección es el método válido en la clase de prueba GUI, usaremos como base el método válido de direcciones. Así que vamos a duplicarlo. Arreglemos su nombre. Ahora. Cambiemos el tipo de dirección aquí a la constante segmentada anidada. Y cambiemos aquí la ruta de derivación para comenzar con 49. Vamos a crear esta constante en el tipo de dirección enum. Vamos a crear también la segue anidada para cambiar constante aquí. Aquí, cambiemos el prefijo de la dirección generada al prefijo de dirección P2 SH de red de prueba. Y en lugar de usar el generador de direcciones de segmento, utilizará el generador de direcciones de segmento anidado. Agreguemos este campo a esta clase. Usaremos la anotación auto cableada para inyectarla en esta clase. Vamos a crear esta clase en el paquete api dot services. Lo implementará posteriormente. Volver a la clase de prueba segue anidada Bitcoin recibida. Hagamos los mismos ajustes a los otros métodos de prueba. Ahora vamos a la clase de configuración de direcciones. Vamos a duplicar este bean lo usará como base para crear la configuración anidada segwayed. Permite cambiar estos parámetros a segmento anidado y cambio de segue anidado. Vamos a cambiar este método nombre dos segmentos anidados config. Ahora cambiemos los parámetros de configuración de dirección. El primer parámetro será el tipo de dirección seg anidado. En el segundo argumento, cambiemos las claves de mapa a segmento anidado y cambio de segmento anidado. Y ambos caminos de derivación. Empezaremos con 49. Usaremos el generador de direcciones de segmento anidado como generador de direcciones. Hagamos que implemente la interfaz del generador de direcciones. Vamos a agregar el método de interfaz. Ahora, vamos a establecer cada prefijo de dirección de entorno. El principal entorno neto. Usaremos la constante principal neta P2 del prefijo de dirección SSH. Los entornos de prueba net y reg . Usaremos la constante de prefijo de dirección P2 SH net de prueba. Cambiemos el prefijo ki extendido a la constante principal del prefijo del segmento anidado neto. El emparejador de direcciones será el predicado segue anidado como. Vamos a crear este campo en el comparador de direcciones. Será similar al predicado de segmento anterior. Pero el matcher volverá verdadero si la dirección empieza con tres o dos en su lugar. Ahora, vamos a importarlo aquí. Vamos a usar la constante P2 SSH aquí. Vamos a usar el método script anidado segment address como analizador de script. Utilizará el generador de entrada de segmento anidado como generador de entrada de transacción. Vamos a crear esta clase en el paquete api dot services. Vamos a agregar el método de interfaz. Como el tamaño de entrada más salida. Estableceremos 180 como el tamaño de ScriptSiG 23. Y como el firmante de la transacción utilizará el firmante de transacciones de Segway anidado. Vamos a crear esta clase en el paquete api dot services. Y agreguemos el método de interfaz. Nuestra configuración de segue anidada está lista. Ahora necesitamos implementar el generador de direcciones de segmento anidado, el generador de entradas y el firmante de transacciones. Empecemos con el seg anidado que se dirigiría al generador. Primero, agreguemos una prueba para este servicio en el paquete de prueba api dot services. Extenderá la clase de especificación. Vamos a agregar el siguiente método de configuración. Agreguemos la llamada al método del proveedor de anuncios de seguridad. Agreguemos el generador de direcciones de segmento anidado como campo en esta clase. Y vamos a instanciarlo aquí. Ahora, vayamos a la prueba del generador de direcciones de segmento. Vamos a copiar esta prueba y pegarla aquí. Lo usaremos como base para nuestra nueva prueba. En lugar de usar el generador de direcciones de segmento, utilizará el generador de direcciones seg anidado aquí. Cambiemos el prefijo a esta constante. Eliminemos estos casos de prueba y peguemos los válidos para las direcciones de segmento anidadas. Están disponibles en la página Proyecto y Recursos. Volver al generador de direcciones de segmento anidado. Creé erróneamente esta clase como una clase maravillosa. Usemos esta característica IDE para convertir esta clase a Java. Eliminemos este código. Agreguemos la anotación de servicio a esta clase. Aquí convertiremos la clave secundaria extendida en una clave pública. Luego devolveremos la dirección del segmento anidado de llamada al método de clave pública comprimida en el objeto obtain pasándole la variable prefix. Cambiemos el nombre de este parámetro a clave extendida. Ahora hagamos esta prueba. Genial, ha pasado. Ahora vamos a implementar el segue anidado qué constructor de entrada. Agreguemos la anotación de servicio a esta clase. Vamos a copiar el método de compilación en el constructor de entrada de segmento y usarlo como base para nuestro nuevo método de compilación. También peguemos estas dos constantes a la clase de constructor de entrada de segue anidada. Ahora agreguemos la constante segmentada anidada scriptSig ficticio en el script ArrayList. Vamos a crear esta constante. Será igual a la cadena cero repetida 44 veces. Aquí, debemos pasar esta constante dentro de una lista de método en realidad. Ahora, implementemos el firmante anidado de transacciones Segway. Agreguemos aquí la anotación de servicio. Copiemos el método de señal en el firmante de transacciones Segway y utilicémoslo como base para nuestro nuevo método de señalización. Aquí, en lugar de usar el método de signo de firmantes ECDSA de transacción, usaremos el método de segue anidado sinusoidal del firmante ECDSA de transacción P2 SH. Agreguemos el script redeem como cuarto argumento en este método. Eliminemos este último argumento. Vamos a crear la variable de script redeem. Esta variable será igual a la llamada al método de script P2 WP k h. Como su parámetro pasará el hash 160 de la clave pública comprimida correspondiente de la clave privada recibida. El método de segue anidado de signo se encargará de agregar el guión redimir al campo testigo y la clave pública y la firma al campo ScriptSIG. Bien, la configuración de segue anidada finalmente está lista. Ahora agreguemos el nuevo campo de segmento anidado a la pestaña Recibir FXML. Primero, cambiemos la dirección de recepción y el texto de la etiqueta para la dirección del segmento. Ahora, vamos a duplicar todo este código y vamos a cambiar este texto de etiqueta a seg anidado abordaría. Cambiemos también esta ética ID dos direcciones de recepción de segue anidadas. Vamos a mover este campo a la segunda fila de su contenedor. Para ello, agreguemos el atributo de índice de fila del panel de cuadrícula a este campo, y vamos a establecerlo en uno. Hagamos lo mismo con esta etiqueta. Ahora, vayamos al controlador de pestañas Recibir. Duplicemos esto si el bloque en esta declaración if verificará si el cambio a dirección es una dirección de segmento anidada. Si es así, entonces estableceremos la dirección de recepción de segue anidada contenido TextField el cambio a dirección. Entonces agreguemos este campo a esta clase. Y vamos a agregarle una anotación FXML. Agreguemos también una declaración de retorno aquí. Ahora, hagamos algunas pruebas. Ejecutemos nuestro nodo Bitcoin. Y hagamos esta prueba. Genial, las pruebas han pasado. En el siguiente video, terminaremos de agregar el soporte de segmentos anidados para nuestra billetera. Verás, sí. 65. 63 skillshare parte 4 de Segwit anidado: En este video, implementaremos la capacidad enviar Bitcoin a segue anidado qué direcciones. Empezaremos por crear pruebas para esa función. Entonces, en el paquete de prueba GUI, vamos a crear la clase de prueba segue anidada de enviar Bitcoin. Extenderá la clase de prueba GUI. Copiemos algunas pruebas de la prueba de enviar Bitcoin. Servirán como base para nuestras nuevas pruebas. Vamos a copiar este código y pegarlo aquí. Ahora, copiaremos esta primera prueba, luego la pegaremos en nuestra nueva clase. Hagamos lo mismo con esta prueba. Hagamos lo mismo con la prueba del anochecer. Ahora, ajustemos las nuevas pruebas. Cambiemos este nombre de prueba para enviar Bitcoin con entradas de segmento anidadas y segue anidado qué salidas. Cambiemos el nombre de la billetera a mi prueba mientras esté a los 23. Y vamos a cambiar este método de búsqueda parámetro de llamada dos segmentos anidados dirección de recepción. Aquí, cambiemos este parámetro a segmento de guión P2 SSH. Este parámetro hará que el nodo devuelva una dirección de segmento anidada para nosotros para que podamos enviarle Bitcoin. Ahora, ajustemos los casos de prueba. Anteriormente he calculado los honorarios totales esperados para estos casos. Se diferencian de las tarifas de transacción con entradas y salidas nativas de segue porque sus tamaños de transacción difieren. Hagamos ajustes similares para la siguiente prueba. Ahora, vamos a crear el generador de scripts P2 SH. Se implementará la interfaz script pub key Builder. Implementemos sus métodos. En el método match devolverá estas llamadas anidadas al método de prueba segue pasando la dirección como su parámetro. Devolveremos la llamada al método de script P2 SH en el método de compilación ya su parámetro pasará la dirección descifrada base 58 así. Agreguemos la anotación de servicio a esta clase. Ahora, vayamos a la prueba de la calculadora de tamaño de transacción. Duplicemos este método. Lo usaremos como base para crear una prueba para verificar el cálculo del tamaño de las transacciones utilizando entradas y salidas de segmentos anidados. Entonces cambiemos el nombre del método para que refleje eso. Eliminemos estos casos de prueba y peguemos los casos de prueba disponibles en la página Proyecto y Recursos. Ahora, en el método setup, agreguemos el seg anidado would config en la lista de configuración de direcciones. Ahora vamos a la calculadora de tamaño de transacción en el método script pub key size. Agreguemos lo siguiente si declaración probará si la dirección recibida es una segue anidada. ¿Qué dirección? Si es así, devolverá el script pub key anidado segwayed constante. Vamos a crear esta constante. Su valor será de 23. Ahora hagamos esta prueba. Genial, ha pasado. Ahora vamos a ejecutar nuestro nodo. Y vamos a ejecutar la prueba de segue anidada de enviar Bitcoin. Genial, las pruebas han pasado. Ahora, juguemos un poco con nuestra billetera en el entorno de red de prueba. Para ello, cambiemos esta variable en el archivo bitcoin.com para probar net. Y reiniciemos nuestro nodo. Esperemos a que se sincronice. Dependiendo de qué tan actualizada esté tu nota. Puede tomar de minutos a horas. Bien, ponderé la suma de horas. Y por último, mi aviso de sincronización. Ejecutemos nuestra aplicación. Vamos a crear una cartera. Primero. Recibamos algunos Bitcoins en nuestra dirección de segmento anidada. Para ello, usemos este grifo. Bien, la transacción apareció en mi billetera. Esperemos un poco a que se confirme. Bien. Ahora la transacción tiene una conformación. Ahora, enviemos algunos fondos a la dirección del grifo. Curiosamente, esta transacción no necesitó cambios y terminamos sin fondos ya que hemos gastado nuestro único insumo. Comprobemos la última transacción en el explorador de bloques. Esperemos un poco a que se confirme. Esperé algunos minutos, y ahora tiene tres conformaciones. El Explorador de Bloques muestra lo mismo. Genial. Todo está funcionando como se esperaba. Hagamos una prueba más. Vamos a recibir más Satoshi primero en nuestra dirección de segmento, luego en nuestro seg anidado se dirigiría. Bien, ahora que ambas transacciones confirmadas, enviemos algunos fondos a una dirección de segmento anidada desde esta página. Ahora la transacción generó cambio. Como lo enviamos a una dirección de segmento anidada, el cambio generado también se envió a un segue anidado. ¿Qué dirección? Después de un tiempo, se confirmó la transacción. Genial. 66. 64 skillshare 2: En este video, implementaremos en nuestra billetera la capacidad de enviar bitcoins a direcciones P2 pKa H, también conocidas como direcciones heredadas. P2, pk h fue el tipo más utilizado para vestir antes del aumento de popularidad de las direcciones de segmento en los últimos años. Hoy en día, sigue siendo muy popular. Por lo que es importante que nuestra billetera tenga la capacidad de enviar bitcoins a esas direcciones. Empecemos por refactorizar cómo nuestra billetera construye claves de pub de script para que sea más fácil agregar soporte para enviar bitcoin a otros tipos de direcciones en el futuro. Para ello, vamos a crear el registro de configuración de script en el paquete de dominios. Similar a la configuración de la dirección, esta clase contendrá parámetros importantes para construir transacciones a tipos específicos de claves de pub de script. Entonces, vamos a agregarle los siguientes campos. El generador de claves de pub de script, el tamaño de la clave de publicación y el predicado del comparador de direcciones, lo que ayudará a identificar el tipo de configuración del script por dirección. Ahora vamos a crear la clase de configuración de script en el paquete api dot config. Nuevamente, similar a la clase de configuración de direcciones. Esta clase será responsable de instanciar y definir todo script pub key es nuestra billetera puede enviar Bitcoin a. Vamos a agregarle la anotación Configuración. Ahora, vamos a crear el siguiente método anotado de Bean. Devolverá una configuración de script y definirá la configuración P2 WP. Es script pub key builder será el constructor de scripts P2 WP k h. El tamaño del script será igual a 22 y su comparador de direcciones será el segmento Lambda. Vamos al constructor de scripts P2 WP k h. Para facilitar la creación de instancias, eliminará del servicio la fábrica de prefijos de dirección . Construirá la variable de prefijo mediante el análisis del prefijo de la variable address usando el método parse prefix. Vamos a crear este método. Primero verificaremos si la dirección comienza con la constante de prefijo de dirección P2 WP k h net de prueba. Si es así, devolveremos esa constante. Entonces haremos la misma declaración, pero usando la prueba reg P2 WP k-ésima dirección prefijo constante en su lugar. Finalmente, devolveremos la constante principal neta P2 WP k h prefijo de dirección si el código se ejecuta a este punto. Ahora vamos a crear el bean para la configuración del script P2 SH. Utilizará el generador de scripts P2 SH. Su tamaño será 23 y su comparador de direcciones será el segmento lambda anidado. Ahora vamos a crear la configuración del script encontrar su clase en el paquete api dot services. Como su nombre indica, este servicio se encargará de encontrar la configuración de script adecuada para otros servicios. Vamos a agregarle la anotación de servicio. Ahora, vamos a inyectar la lista de configuraciones de script en esta clase. Spring Boot magic inyectará todos los beans de configuración de script en esta lista después de que se inicie la aplicación. Ahora, vamos a crear el hallazgo por método direccionada. Devolverá una configuración de script y tomará una dirección como parámetro, devolverá la siguiente transformación de flujo aquí filtrará el script puede pensar stream usando el comparador de direcciones de cada script config. Usaremos para encontrar el primer método para obtener la primera configuración de script filtrada. Si no encontramos ninguna, usaremos el método de lanzamiento de URL para lanzar una excepción. Ahora, vamos al servicio de creadores de transacciones que usaremos el buscador de configuración de script para refactorizar esta clase. Primero, eliminemos la lista de creadores de claves de pub script de esta clase ya que no la usaremos. Y vamos a inyectar el script puede pensar Finder en esta clase. Ahora en el método de salida de compilación, eliminemos este código. Se creará esta variable de script utilizando el buscador de configuración de script, encontrar por el método direccionado. Luego llamaremos al método de compilación script pub key builder sobre el resultado. Ahora, vamos a refactorizar la calculadora de tamaño de transacción. Inyectemos el buscador de configuración de script en esta clase. Ahora, vamos a eliminar el código en el método script pub key size, en su lugar utilizará el script config Finder para encontrar una configuración de script por dirección y devolver su tamaño de clave pub script. Eliminemos estas importaciones y constantes ya que no las usaremos. Ahora, vamos a la interfaz script pub key Builder. Eliminemos el método match de él y de todas sus implementaciones, ya que ya no lo usaremos. Se realiza la refactorización. Ahora antes de agregar el P2 pKa H Script Config permite crear la prueba heredada de enviar Bitcoin en el paquete de prueba GUI. Extenderá la clase de prueba GUI. Usaremos esta clase para verificar si nuestra billetera está enviando correctamente una transacción a una dirección heredada. Copiemos el siguiente código de la prueba de enviar Bitcoin y pegarlo aquí. Lo usaremos como base para nuestra nueva prueba. Cambiemos su nombre a debería enviar Bitcoin con entradas de segmento, salida heredada y seg cambiaría. Observe que aunque podremos enviar fondos a una dirección heredada, no podremos recibirlos una dirección heredada que pertenezca a nuestra billetera. Por lo tanto, utilizará las direcciones nativas de segue para recibir el cambio en estas transacciones. Y ese nombre de prueba refleja eso. Cambiemos el nombre de la billetera a mi prueba mientras esté a los 26. Cambiemos este parámetro a legacy para que podamos crear una dirección heredada a la que usaremos para enviar bitcoins. Cambiemos también los casos de prueba usando los siguientes valores calculados previamente. Estos valores difieren de otras transacciones porque las claves P2, pKa, H script pub son un poco más grandes que las claves de pub script nativas de segue , lo que afecta el tamaño de la transacción y phi. Ahora vamos a la clase de configuración del script. Agreguemos aquí la palabra clave pública. Vamos a crear el bean de configuración P2 pKa H ya que su script pub key builder establecerá un nuevo generador de scripts p2 pk H, que creará más adelante. Su tamaño de clave de pub guión será de 25 y está abordado. Parcher serán estos Lambda heredados que crearemos más adelante. Vamos a crear el constructor P2 pKa H Script en el paquete api dot services. Vamos a implementar el método de interfaz. En el método build devolverá el script P a P k h la llamada al método script ya su parámetro pasará la dirección decodificado hexadecimal base 58 usando la base 58 decodificar con el método checksum a hex. Ahora, vayamos a la clase métrica de dirección. Duplicemos este campo. Lo usaremos como base para estos lambda heredados. Aquí se cambiarán estos parámetros a uno, M y N. Uno es el prefijo de legado que viste en la red principal. M y n son los prefijos válidos para los demás entornos. Importemos aquí estos lambda heredados. Bien, ahora nuestra billetera puede enviar Bitcoin a direcciones heredadas. Ahora, ajustemos algunas pruebas. Vamos a la prueba de la calculadora de tamaño de transacción. En el método de configuración, Instanciemos el buscador de configuración del script. pasaremos una lista de configuraciones de guiones. Tomará las configuraciones de script de la clase de configuración de script. Entonces vamos a instanciarlo aquí. Ahora, vamos a agregar el script puede higos aquí. Ahora, vamos a duplicar esta prueba. Vamos a cambiarle el nombre a debería calcular el tamaño de la transacción para P2 WP k-ésima entradas de transacción y p2 pk salidas de cada transacción. Este nombre de prueba describe bien el escenario probará. Eliminemos estos casos de prueba. Pegará estos casos de prueba aquí los cuales están disponibles en la página Proyecto y Recursos. Arreglemos el formato de estos casos de prueba. Vamos a ejecutar esta prueba. Grado. Ya pasaron las pruebas. Ahora, arreglemos la prueba de servicio de creadores de transacciones. Vamos a copiar este código y pegarlo aquí. Eliminemos la fábrica de prefijos de dirección y los creadores de claves de pub script. Y arreglemos la instanciación del servicio aquí. Vamos a ejecutar esta prueba. Genial, ha pasado. Ahora arreglemos la prueba del selector de monedas de sorteo aleatorio único necesitará esta pieza de código nuevamente. Así que vamos a copiarlo y pegarlo aquí. Asegúrese de que el selector de monedas de sorteo aleatorio único esté instanciado correctamente. En mi caso, la identificación ya lo hizo. Vamos a ejecutar esta prueba. Grado. La prueba ha pasado. Ahora, vamos a ejecutar nuestro nodo. Antes de eso, asegúrese de que el archivo bitcoin.com tenga el entorno de prueba reg establecido. Ahora vamos a ejecutar la prueba heredada de enviar Bitcoin. Genial, La prueba ha pasado. 67. 65 Guardar skillshare 2: En los videos anteriores, implementamos una aplicación completamente funcional que ya puedes usar para crear billeteras y enviar y recibir Bitcoins. Pero si cerramos la aplicación, perdemos toda la información sobre las billeteras que creamos en este video y en el siguiente, comenzaremos a implementar la capacidad guardar y cargar billeteras en nuestra aplicación. Para almacenar los datos de nuestra aplicación, utilizaremos la base de datos H SQL. Sql es una base de datos SQL implementada en Java. Hemos elegido H SQL por las siguientes razones. Primero, es una base de datos ligera. En segundo lugar, es compatible y fácil de usar con la biblioteca Spring Boot Data JPA. Por último, se puede cifrar fácilmente como lo mostraremos en este video. Vamos al archivo XML poema punto para agregar las dependencias Spring Boot Data JPA y H SQL DB. Haga clic en este botón para cargar las nuevas dependencias. Ahora vamos al archivo de propiedades del punto de la aplicación. Vamos a establecer algunas configuraciones necesarias para la base de datos. Esta configuración determina que cada modificación que hagamos en nuestras clases de entidad, actualizaremos nuestra base de datos en consecuencia. En Spring Boot, las clases anotadas de entidad definían las estructuras de tabla, como veremos pronto. Duplicemos esta línea para usarla como base para las otras configuraciones. Tenemos que establecer la clase de controlador llamada config a la siguiente clase. El nombre de usuario y la contraseña. Puedes ponernos lo que quieras. Como lo estoy usando solo para pruebas, estableceré estos campos para que sean Y0 W por ahora. Pero recuerde cambiar estos valores a cadenas más seguras antes de usar esta billetera en la red principal. Ahora, definamos la URL de la base de datos. Ya que vamos a utilizar una base de datos basada en archivos, tendremos que establecer esta configuración JDBC colon colon H SQL DB archivo colon, la ruta que queremos que residan los archivos de la base de datos. En mi caso, el camino comenzaremos con la carpeta BYOD W ubicada en el asiento dr. Raíz. Dentro de esta carpeta, quiero crear carpetas específicas para cada entorno de red Bitcoin. Para ello, me referiré a la variable de entorno Bitcoin en este archivo de propiedades de punto de aplicación, poniéndolo entre llaves y después de un signo de $1 así. Finalmente, usaré la subcarpeta de datos dentro esta carpeta y nombraré los archivos DB como mi DB. Y terminamos la línea con punto y coma. Ahora dentro del paquete BYOD W, vamos a crear el paquete de base de datos. Dentro de este paquete, vamos a crear el paquete de entidades. Y vamos a crear la clase de entidad wallet dentro de ella. En esta clase, modelaremos registros en la tabla de la base de datos de billeteras. Para ello, le agreguemos la anotación de entidad. Y la anotación de tabla con su parámetro de nombre igual a Wallet. Ahora, agreguemos algunos campos a esta clase. Cada campo en esta clase, modelaremos una columna de la tabla de billetera. Nuestro objetivo es guardar solo los campos necesarios para obtener los mismos datos de billetera después de cargarlo. Entonces agreguemos el campo ID. Se agregará este campo para seguir la buena práctica de agregar siempre un identificador de incremento automático a una tabla de base de datos relacional. Para ello, agreguemos dos anotaciones a este campo. La primera es la anotación de ID, la segunda es la anotación de valor generada con el siguiente parámetro. También agreguemos una anotación de columna con ID como parámetro de nombre. La anotación de columna determinará el nombre correspondiente de la columna enlazada a este campo en la tabla de billetera. Seguiremos el estilo de caso serpiente para los parámetros de nombre de columna donde todas las letras o minúsculas y subrayado separan las palabras. Ahora vamos a crear el campo de nombre. Agreguemos también la anotación de columna a este campo. Además del parámetro name, agreguemos también el parámetro unique equals true y el parámetro nullable igual a false. Estos parámetros agregarán las restricciones únicas y no anulables en la tabla para esta columna. Por lo tanto, la aplicación generará un error si intentas crear un registro sin nombre en la tabla de billetera. Creemos también el campo semilla mnemotécnico con la siguiente anotación. El parámetro length limitará la longitud máxima de este campo a 500 caracteres. Agreguemos también el parámetro nullable equal false a esta anotación. Ahora, agreguemos el campo número de direcciones generadas con la anotación de columna siguiendo el estilo de caso de serpiente. El último campo será el creado en. Agreguemos la anotación de fecha creada para indicar que este campo utilizará la fecha actual para registrar sus valores. Ahora, vamos a crear algunos constructores. Primero, un constructor vacío, que es necesario para que Spring Boot instancie esta clase correctamente. A continuación, vamos a crear un constructor con todos los campos de esta clase excepto el id. Vamos a crear getters para los mismos campos. Nuestra entidad de billetera está hecha. Ahora dentro del paquete de base de datos, vamos a crear el paquete repositorios. Y vamos a crear la interfaz del repositorio de billeteras dentro de ella. La interfaz del repositorio de billeteras será responsable de interactuar con la base de datos recuperando datos y guardando datos en la tabla de billetera. Para lograrlo, extenderá interfaz del repositorio JPA agregará parámetros de tipo a esta extensión. La primera prueba para ser la entidad que este repositorio vamos a gestionar. En este caso, será la clase de entidad wallet. El segundo tiene que ser el tipo de identificación de la entidad. Por lo tanto, será la clase larga. Con esta sencilla interfaz, ya tenemos acceso a operaciones comunes de base de datos para la tabla de cartera, como insertar registros y encontrarlos por ID. Todo esto es traído automáticamente a usted por la biblioteca Spring Boot Data JPA. Ahora vamos a crear el paquete de servicios en el paquete de base de datos. En su interior, vamos a crear la clase de servicio de guardar billetera. Esta clase se encargará de guardar la cartera después de su creación. Vamos a agregarle la anotación de servicio. Inyectemos el repositorio de billeteras en esta clase. Hagamos lo mismo con el número inicial del campo de direcciones generadas. Ahora, vamos a crear el método de guardar billetera. Tomará como parámetro un objeto wallet. Para implementar. Primero instanciará un nuevo objeto de entidad de billetera con los siguientes parámetros de la billetera. Después llamaremos al método save del repositorio de billetera, pasando a la entidad wallet como su parámetro. *****. Aquí mezclé el orden de los parámetros. Vamos a arreglarlo. Y agreguemos aquí la anotación calificador para la correcta inyección de este campo. Eso es. Con este sencillo código, logramos guardar la información de la billetera la base de datos SQL fácilmente. Ahora vamos a crear el paquete de oyentes en el paquete de base de datos. Y vamos a crear una clase llamada save wallet listener. En su interior. Esta clase servirá como oyente para el evento de billetera creado. Para que después de que la aplicación cree una billetera, se encargará de llamar al servicio de guardar billetera para guardar la billetera. Entonces vamos a agregarle la anotación de componente. Implementará el oyente de aplicaciones con el evento de billetera creado como su parámetro de tipo. Implementemos su método. Aquí, llamaremos al método guardar billetera, pasando la billetera de eventos como su parámetro. Vamos a crear este método. Usaremos el servicio de guardar billetera aquí. Entonces vamos a inyectarlo en esta clase. Entonces llamaremos aquí al método guardar billetera, pasando la billetera como su parámetro. Ahora, si todo funciona correctamente, nuestra aplicación guardará billeteras en la base de datos después de su creación. Así que vamos a ejecutar nuestra aplicación para probar esta característica probará primero en el entorno de prueba reg. Asegúrese de que la opción VM en la configuración de ejecución de la aplicación BYOD W esté vacía. Para esta prueba específica, no necesitaremos ejecutar nuestro nodo. Vamos a ejecutarlo. Vamos a crear una cartera. Bien, si todo funcionó correctamente, se guardó la billetera. Cerremos nuestra aplicación. Ahora. Veamos si los archivos de la base de datos fueron creados en la carpeta especificada. Genial, la aplicación creó la carpeta reg test y los archivos DB esperados en ella. Vamos a abrirlos. Archivo de registro de puntos IDB. Aquí podemos ver todas nuestras operaciones de bases de datos de aplicaciones en SQL escritas en texto plano. Podemos ver que tiene un comando insert que contiene datos de wallet, incluyendo su semilla mnemotécnica. Bueno. Pero esto no se guarda ya que cualquiera que obtenga este archivo puede conocer todas nuestras billeteras, semillas mnemotécnicas. Lo arreglaremos pronto cifrando estos archivos. Por ahora, veamos los datos de la billetera guardada en un formato más legible. Para ello, vayamos a esta página web para descargar el H SQL DB. Haga clic en el enlace de descarga para descargar la última versión. Después de descargarlo, extrae su contenido a una carpeta. Vamos a abrir la carpeta bin ubicada dentro de la carpeta extraída. Ahora vamos a ejecutar los gerentes de ejecución swing puntear ese archivo. Vamos a la aplicación dot properties en nuestra aplicación para copiar la URL de la base de datos. Ahora, vamos a pegar su contenido en este campo. Y sustituyamos esta variable por la prueba reg. Agreguemos aquí el mismo nombre de usuario y contraseña que definimos en nuestro archivo de propiedades de punto de aplicación. Vamos a hacer clic. Bien, genial. Hemos logrado conectarnos a nuestra base de datos. Ahora, haga clic con el botón derecho en la carpeta de billetera pública de puntos aquí y haga clic en la instrucción SQL select. Ejecutemos este comando haciendo clic en este botón. Genial. Aquí están nuestros datos de billetera en formato de tabla. Podemos ver que nuestra aplicación guardó con éxito los datos de la billetera. Cerremos esta aplicación. Ahora, como dije antes, es importante que encriptemos nuestros archivos de base de datos. Para ello, agreguemos el siguiente sufijo a la URL de la base de datos en el archivo de propiedades de punto de la aplicación. Aquí definiremos una clave criptográfica y encriptaremos el tipo. El tipo cuna será AES, que es una criptografía simétrica que la aplicación utilizará para cifrar los datos antes de guardarlos en la base de datos y descifrar los datos al recuperarlos. La clave cripta será la clave necesaria para ambas operaciones. Volvamos a usar el administrador de bases de datos SQL para generar una clave cripta válida. Haga clic en el botón Bien aquí. Ejecutemos el siguiente comando SQL. Vamos a copiar la clave generada en un editor de texto, luego copiarla de nuevo al valor de la clave crypt en las propiedades de punto de la aplicación. Ahora agreguemos la misma configuración de base a los otros archivos de propiedades del proyecto. Vamos a eliminar la carpeta reg test, crear un distorsiona los archivos de la base de datos. Y volvamos a ejecutar nuestra aplicación. Vamos a crear una nueva cartera. Ahora, vamos a abrir la carpeta reg test y el archivo log generado my db dot. Su contenido es completamente ininteligible ahora, eso significa que se cifró con éxito. Volvamos a copiar la URL de la base de datos, incluyendo el sufijo de cifrado y abrirla usando el administrador H SQL DB. Genial, podemos volver a ver los datos de la billetera guardada usando la nueva URL en esta aplicación. 68. 66 cartera de carga parte 1 skillshare 2: En este video, comenzaremos a implementar la capacidad de cargar billeteras previamente guardadas en nuestra aplicación. Primero, hagamos alguna refactorización necesaria. Vamos al servicio de crear monedero. Queremos poder crear billeteras con diferentes fechas y números de direcciones generadas. Entonces agreguemos estos como parámetros en este método. Ahora, sustituyamos esta instanciación de fecha por la variable created at. Y agreguemos la variable número de direcciones generadas como último parámetro de este método. Ahora, vayamos al controlador de diálogo create wallet para agregar estos parámetros a la llamada al método create. Inyectemos el número inicial de direcciones generadas en esta clase. Ahora, cambiemos la firma del método de direcciones ADA para incluir el último parámetro que acabamos de agregar a esta llamada. En el servicio de direcciones ADD, agreguemos la variable número de direcciones generadas a este método llamada y firma. También pasémoslo como último parámetro del método de generación de generador secuencial de direcciones. Cambiemos la firma de este método para incluir este parámetro. Ahora, eliminemos el número inicial de campo de direcciones generadas de esta clase. Y vamos a sustituirla aquí por la variable número de direcciones generadas. Ahora vamos a ir a la actualización actual del servicio de direcciones de cartera establecerá el número inicial de direcciones generadas como el último parámetro de esta llamada al método. Ahora vamos a crear la clase de prueba de billetera de carga en el paquete de prueba GUI. Extenderá la clase de prueba GUI. Pasemos a la prueba de enviar Bitcoin para copiar esta parte del código, ya que la necesitaremos para nuestra nueva prueba. Y vamos a pegarlo aquí. Ahora, vayamos a la clase de prueba de Bitcoin receptora. Copiemos esta primera prueba y utilicémosla como base para nuestra nueva prueba. Vamos a renombrarlo a debería cargar billetera y recibir Bitcoin. Vamos a formatear esta prueba. Agreguemos un bloque dado a esta prueba. Aquí, vamos a definir un nombre de billetera y variables de contraseña. Definamos también una variable semilla mnemónica. Usaremos el método de creación del servicio de semillas mnemotécnicas para generarlo. Inyectemos el servicio de semillas mnemotécnicas en la clase de prueba GUI. Ahora, llamemos aquí al método create wallet, pasando el nombre de la billetera, la contraseña y la semilla mnemotécnica como sus parámetros. Vamos a crear este método en la clase de prueba GUI. Aquí, crearemos un Wallet usando el servicio create wallet. Así que vamos a inyectarlo en esta clase. Ahora, llamemos al método create pasándole estos parámetros. Ahora usaremos el servicio de guardar billetera. Así que vamos a inyectarlo en esta clase. Y vamos a llamarlo método guardar billetera, pasando la billetera como su parámetro. Por último, devolvamos la cartera aquí. Volver a la prueba de billetera de carga. Ahora que hemos creado y guardado una billetera intentaremos cargarla. Así que vamos a eliminar este código. Llamemos al método load wallet, pasando el nombre de la billetera como su parámetro. Vamos a crear este método en la clase de prueba GUI. También tomará un parámetro de contraseña opcional con una cadena vacía como su valor predeterminado. Primero, intentaremos hacer clic en un componente con la carga de textos. Este componente será el botón de menú de carga, que estará junto al botón Nuevo en el menú en la parte superior de la ventana principal. Después moveremos el mouse a un componente con la billetera de texto. Después de eso, esperaremos que aparezca un submenú que contenga todos los nombres de billetera cargados. Después haremos clic en el que tenga el texto igual a la variable wallet nombrada. A continuación, esperaremos que aparezca una ventana de diálogo con un campo de entrada de contraseña y un botón Ok. Entonces haremos clic en este campo que tiene el ID de ética de contraseña de la billetera de carga. Ahora vamos a escribir la contraseña en ese campo. Después haremos clic en el botón Bien. Por último, llamemos al método sleep para esperar a que se cargue la billetera. Bien, el resto de la prueba será igual las pruebas de billetera receptora que hemos utilizado como base para esta prueba enviarán Bitcoin a la billetera cargada y esperarán que las direcciones y tablas de transacciones sean lleno de valores apropiados. Ahora, vayamos al archivo FXML punto playground para diseñar el menú de carga. Agreguemos un control de menú a la barra de menús. Cambiemos su texto para cargar. Ahora, agreguemos un control de menú al menú de carga. Eliminemos este elemento del menú que se agregó automáticamente. Cambiemos los textos de este menú a billetera. Y eliminemos este elemento del menú. Ahora en la vista del editor de texto, agreguemos un Fx ID a esta etiqueta de menú. Vamos a configurarlo para cargar el menú FXML. Vamos a agregarlo al controlador de ventana principal. Agregará una anotación FXML y la cambiará a un campo privado. Ahora, agreguemos la clase de menú de carga en el paquete observables. Esta clase se encargará de administrar los elementos del menú que se agregarán para cada billetera que creamos en nuestra aplicación. Vamos a agregarle una anotación de componente. Vamos a crear el campo de elementos del menú aquí. Será un conjunto observable de entidad tipo wallet. Lo instanciaremos usando un nuevo envoltorio de conjunto observable, pasándole un nuevo LinkedHashSet. Ahora vamos a crear aquí el buen método de elementos de menú observables. Devolverá los elementos del menú. Ahora vamos a crear el listener de menú de carga en el paquete de escucha de puntos GUI. Este oyente se activará por el evento pegajoso iniciado publicado después de que se inicie la aplicación. Lo usaremos para cargar todas las billeteras guardadas en la base de datos y agregarlas al menú de carga. Vamos a agregarle una anotación de componente. Implementará la clase de escucha de aplicaciones con el evento iniciado GUI como su parámetro de tipo. Implementemos su método. Usaremos el repositorio de billeteras aquí. Así que vamos a inyectarlo en esta clase. También vamos a inyectar el menú de carga en esta clase. Después llamaremos al método final para cargar todas las billeteras de la base de datos. Para cada monedero se llamará al método add wallet. Vamos a crear este método envuelto en la plataforma ejecutar más tarde llamada, vamos a llamar al método load menu add, pasando la entidad wallet como su parámetro. Vamos a crear este método y la clase de menú de carga. Aquí simplemente llamaremos al método add items menu pasando la entidad wallet como su parámetro. Ahora vamos a copiar esta línea. Pasemos a la clase de servicio Guardar billetera. Lo pegaremos aquí. Inyectemos el menú de carga en esta clase. Con este código, hará que nuestra billetera recién guardada se agregue al menú de carga. Ahora, vamos al patio de recreo punto FXML. Vamos a copiar estas líneas y pegarlas en la ventana principal FXML. Ahora, vayamos al controlador de ventana principal. En el método inicializado vinculará todos los cambios en el menú de carga observables al menú de carga. componente fxml necesitará el menú de carga aquí. Así que vamos a inyectarlo en esta clase. Ahora, llamemos al método get observable menu items en él. Y llamemos al método de escucha de anuncios en el resultado como su parámetro. Pasaremos la siguiente Lambda. El cuerpo Lambda obtendrá el elemento agregado y lo almacenará en la variable wallet así. Entonces usaremos una declaración if para verificar si el menú contiene la billetera así. Vamos a crear este método. Mediante la siguiente transformación de flujo se verificará si el menú de carga FXML contiene un elemento de menú con el mismo nombre que la variable de entidad de billetera. Aquí, si el menú de carga FXML no contiene la cartera, se procederá a agregarla a la misma. Instanciará un objeto de elemento de menú pasando como su parámetro, el nombre de la billetera. Después agregaremos el elemento del menú al menú de carga FXML, así. Ahora, vayamos a la clase de prueba GUI en el método de inicio antes de que cada prueba limpie la base de datos para que las billeteras, los nombres duplicados de madera no sean persistidos. De esa manera, evitamos los bloqueos de prueba debido a la restricción de nombre único en la tabla de billetera. Aquí necesitaremos el repositorio de billeteras. Así que vamos a inyectarlo en esta clase. Después llamaremos al método delete all en él. Ahora, vamos a ejecutar nuestro nodo. Y vamos a ejecutar la prueba de billetera de carga. Bien, la prueba corrió hasta la parte esperada y falló. Pudimos ver que nuestro menú de carga fue creado y poblado con el nombre de billetera creado. Bueno. En el siguiente video, seguiremos implementando esta característica, C. Sí. 69. 67 Cartera de carga parte 2 skillshare: En este video, continuaremos implementando la función de billetera de carga. Para comenzar, construiremos una ventana de diálogo que aparecerá después de hacer clic en el nombre de la billetera que queremos cargar y el menú de carga como base para construirla, usaremos el diálogo crear billetera. Entonces vamos al diálogo crear billetera FXML. Vamos a copiar todo este contenido. Vamos a crear el archivo FXML de diálogo de billetera de carga en el paquete FXML. Y vamos a pagar El contenido copiado aquí. Cambiemos el texto del encabezado del diálogo a la siguiente frase. Cambiemos el atributo de altura pref a 300. También eliminemos estas líneas. Vayamos al Scene Builder para ver cómo se ve. Cambiemos este texto de etiqueta a contraseña de billetera. En la vista del editor de texto, cambiemos este fx ID para cargar la contraseña de la billetera. Y cambiemos el controlador FX de la etiqueta de dolor de diálogo para cargar el controlador de diálogo de billetera. Vamos a crear este controlador. Vamos a agregarle la anotación de componente. Y agreguemos todos estos campos FXML al controlador. Ahora, vamos al controlador de la ventana principal aquí antes de agregar el elemento de menú al menú de carga FXML, llamaremos al método set on action en él, pasándole el siguiente Lambda. Esto hará que la aplicación ejecute el método de diálogo de billetera de carga abierta, pasando la billetera como su parámetro después de hacer clic en este elemento del menú. Así que vamos a crear este método. Copiemos el contenido del método de diálogo open create wallet y utilicémoslo como base para nuestro nuevo método. Vamos a establecer el título del diálogo para cargar billetera. Cambiemos el primer parámetro de instanciación del cargador FXML al campo de diálogo de carga de billetera. Inyectemos este campo en esta clase. Agreguemos aquí esta anotación de valor y cambiemos su parámetro al archivo FXML de la billetera de carga. Ahora, tenemos que pasar la billetera al controlador de diálogo de la billetera de carga. Para ello, primero obtengamos el controlador del cargador FXML. Entonces llamemos a este método set wallet en él, pasándole la billetera. Vamos a crear este método. Aquí. Simplemente estableceremos el campo de entidad de billetera en la variable wallet. Vamos a crear este campo. Ahora, vamos a crear el método inicializado que se ejecutará después de que aparezca el diálogo. Vamos a copiar este código y el controlador de diálogo create wallet y pegamos aquí. Esto establecerá la acción de cerrar la ventana de diálogo en el botón de cancelar. También copiemos y peguemos este código al nuevo método inicializado. Establecerá la acción del botón Bien. Pero en lugar de llamar al método create wallet, llamará al método load wallet. Vamos a crearlo. Primero. Recuperaremos una nueva entidad de billetera de la base de datos y la estableceremos como el campo de entidad de billetera. Para ello, necesitaremos el repositorio de monederos. Así que vamos a inyectarlo en esta clase. Después llamaremos al método find por su nombre en él, pasándole el nombre de la entidad monedero. Vamos a crear este método. El método será así. Spring Boot Data JPA magic traducirá automáticamente este nombre de método en una consulta SQL y recuperará la entidad de billetera con el nombre pasado como parámetro de la base de datos. Ahora, crearemos un objeto wallet. Para ello, necesitaremos crear un servicio de monedero. Así que vamos a inyectarlo en esta clase. Llamaremos al método create pasando los siguientes parámetros. Todos estos parámetros excepto la contraseña del monedero, serán tomados de la entidad wallet que se encuentra en la base de datos. La contraseña se tomará del campo de contraseña de diálogo. Inyectemos el objeto context en esta clase. Ahora, usando el contexto se publicará un evento de billetera cargada pasándole esta y la billetera creada. Finalmente, llamaremos al método hide para cerrar así la ventana de diálogo. Vamos a crear la clase de evento de billetera cargada. Pasará el parámetro load wallet dialogue controller al super constructor. Y estableceremos el campo wallet en el parámetro constructor wallet. Vamos a crear un getter para el campo de la billetera. Ahora, hagamos alguna refactorización en el oyente de importación de billetera creado. Queremos que sea para escuchar eventos de billetera cargada. Pero tal como es ahora, solo puede escuchar el evento de billetera creado. Para cambiar eso, vamos a eliminar esta sentencia implement y esta anotación Override. Cambiemos el nombre de este método para importar wallet y su parámetro a un objeto wallet. Cambiemos el parámetro del método de importación de billetera a Wallet. Ahora vamos a crear un método anotado con la anotación del oyente de eventos. Se llamará en el evento de billetera creado, y recibirá un evento de billetera creado como su parámetro. Aquí llamaremos al método import wallet, pasando como parámetro el monedero del evento. Esta refactorización seguirá haciendo que las cosas funcionen como antes. Pero ahora, si queremos escuchar otro evento, podemos simplemente crear otro método anotado de oyente pasando el evento que queremos como su parámetro. Eso es exactamente lo que haremos ahora usando el evento load wallet también llamará al método import wallet aquí, pasando la billetera de eventos como su parámetro. Eso hará que el nodo Bitcoin importe la billetera, al igual que cuando creamos una nueva billetera. Ahora, vamos a crear la clase de escucha de billetera cargada en el paquete de oyentes. Vamos a agregarle la anotación de componente. Vamos a crear un método anotado de oyente llamado evento de billetera descargada. Tomará como parámetro un evento de cartera cargado. Aquí llamaremos al método load wallet pasando el event wallet como su parámetro. Vamos a crear este método. Aquí. Necesitaremos la actualización actual del servicio de monedero. Así que vamos a inyectarlo en esta clase. Y llamaremos al método de actualización en él. Al pasar la billetera como su parámetro también se necesitará la actualización del servicio UTXOS. Así que vamos a inyectarlo en esta clase. Después llamaremos al método de actualización en él, pasando las direcciones y el nombre de la billetera como sus parámetros. Con estas dos líneas de código, esperamos que la billetera actual se cambie a la billetera cargada y sus direcciones, transacciones y saldos se actualicen en consecuencia. Ahora arreglemos algunas pruebas. Se rompieron los videos anteriores en la prueba del generador secuencial de direcciones. Eliminemos este primer parámetro en la instanciación del generador secuencial de direcciones. Y fijemos 20 como último parámetro de este método. Vamos a ejecutar esta prueba. Genial, está funcionando como se esperaba. Hagamos lo mismo con la prueba de crear el servicio de monedero. Bien, está funcionando. Ahora. Vamos a ejecutar nuestro nodo. Limpiemos y compilemos el proyecto usando esta función IDE de Maven. Y vamos a ejecutar la prueba de billetera de carga. Falló. El problema está en el controlador de ventana principal. Aquí tenemos que llamar al método FXML loader get controller en lugar del método load. Realicemos de nuevo la prueba. Genial, Ha pasado. 70. 68 cartera de carga parte 3 skillshare 2: En este video, agregaremos más pruebas y haremos algunas optimizaciones a la función de billetera de carga. Una de las características que tendrá nuestra cartera es la negación plausible. La negación plausible en este contexto es una característica de seguridad que te permitirá ocultar las direcciones de tu billetera ingresando una contraseña diferente para cargar tu billetera. Eso significa que nuestra billetera no tendrá contraseñas incorrectas. Cada contraseña ingresada dará acceso a un conjunto diferente de direcciones, pero observar a terceros no podrá decir si las direcciones de billetera cargadas tienen la mayor parte de tus fondos. Vamos a crear una prueba para este escenario. Duplicemos esta prueba y utilicémosla como base para nuestra nueva prueba. Vamos a renombrarlo a debería cargar billetera con diferente contraseña y recibir Bitcoin. Vamos a reformatear. Aumentemos el número de billetera con nombre. Ahora definamos esta variable de contraseña diferente y pasémosla al método load wallet como su segundo argumento. También pasémoslo como último parámetro del método válido de direcciones. Vamos a establecer el parámetro password como un parámetro opcional para este método, estableciendo su valor predeterminado en una cadena vacía. Sustituyamos la cadena vacía y el método de dos claves maestras por la variable de contraseña. Vamos a ejecutar nuestro nodo. Comentemos este método y ejecutemos nuestra nueva prueba. Genial, ha pasado. Esta prueba muestra que nuestra aplicación ya admite cualquier contraseña para cargar una billetera y que cada contraseña generará un conjunto separado de direcciones. Vamos a descomentar esta prueba. Dada nuestra forma de ver una billetera como tener múltiples conjuntos de direcciones de acuerdo a sus contraseñas. Tenemos que solucionar un problema en nuestra aplicación. Cuando hacemos llamadas a nuestro nodo Bitcoin a través de nuestra aplicación, usamos nuestro nombre de billetera. Esto es un problema ya que para operaciones como recuperar nuestras transacciones de billetera y UTXOS de nuestro nodo recopilaremos la misma información para diferentes conjuntos de direcciones generados por diferentes contraseñas. Para optimizar nuestra nota las llamadas RPC y recopilar solo información para las direcciones generadas con una contraseña dada, usaremos la primera dirección de recepción generada como el nombre de la billetera importante para nuestro nodo. Para ello, vayamos al registro de la cartera. Vamos a crear el buen método de la primera dirección aquí. Utilizará el método get addresses para devolver la primera dirección de la billetera. Ahora, tenemos que sustituir cada llamada al campo de nombre de billetera que se hizo para comunicarse con nuestro nodo por una buena llamada al método de primera dirección, usemos nuestro ID para identificar los usos de el campo de nombre y hacer la refactorización. Ahora, vayamos a la actualización del servicio de billetera actual y fijemos la primera dirección de la billetera actual. Vamos a crear este método. Aquí. Estableceremos el primer campo de dirección en el parámetro recibido. Vamos a crear este campo. Y vamos a crear un getter para ello. Ahora, sustituyamos relevantes del método getName de la billetera actual por las llamadas al método de obtención de la primera dirección de la billetera actual. Ahora vayamos a la prueba de billetera de carga, comente la primera prueba y ejecutemos la prueba restante. Grandes cosas siguen funcionando como antes. Vamos a descomentar esta prueba. Ahora, vayamos a la clase de configuración de direcciones. Como ahora estamos usando la primera dirección de billetera para interactuar con nuestro nodo, la primera dirección siempre debe ser la misma para una combinación de semilla mnemotécnica y contraseña. Por lo tanto, tenemos que garantizar que la lista de configuraciones de direcciones y sus direcciones siempre estén en el mismo orden. Para ello, usemos la anotación de orden en ambos frijoles. Agreguemos la anotación de orden con cero como argumento en este primer Bean. Esto hará que Spring inyecte este bean en las listas de configuración de direcciones como el primer elemento. Cambiemos también el segundo argumento del objeto address config a un Hashmap vinculado. Contrario a los mapas generados por el mapa de método, el Hashmap vinculado mantiene el orden de inserción, lo logrará utilizando el siguiente código. Ahora hagamos el mismo refactor al otro frijol de configuración de vestido rojo. Y agreguemos aquí la anotación de orden usando uno como su parámetro, garantizando que se inyectará después el primer bean se alista de configuraciones de direcciones. Ahora, hagamos otra optimización. Importar direcciones a nuestro nodo a veces es lento. Para evitar importar innecesariamente direcciones a nuestro nodo comprobaremos si ya están importadas. Para hacerlo, vamos a crear el nodo recibido por cliente de dirección en el paquete de cliente nodo punto. Este cliente recuperará todas las direcciones cargadas actuales por nuestro nodo. Vamos a agregarle la anotación de servicio. Y vamos a inyectar el cliente del nodo en él. Ahora, vamos a crear el método de direcciones de lista aquí. Devolverá una lista de objetos de dirección de nodo como sus parámetros. Tomará un nombre de billetera. Amén conf, que definirá el número mínimo de conformaciones de las direcciones devueltas. El parámetro include empty, que definirá si la llamada devolverá direcciones sin fondos. Y el parámetro include watch only que le dirá al nodo si queremos recuperar direcciones que el nodo no conoce sus claves privadas correspondientes. Vamos a crear el registro de dirección de nodo en el paquete de nodos de punto de dominios. Tendrá sólo un campo de dirección. Usando el cliente del nodo. Hagamos la llamada RPC aquí. Devolverá una matriz de direcciones de nodo. El primer parámetro para el método make request será la lista recibida por cadena de dirección. Luego pasaremos un nuevo objeto de referencia de tipo parametrizado. A continuación, la URL de la billetera. Finalmente, los parámetros del método de vestimenta enumerados los describimos anteriormente. Ahora devolverá una conversión de la matriz de direcciones de nodo en una lista de direcciones de nodo como esta. Ahora, vayamos al servicio de monederos de importación. Aquí agregaremos una declaración if para verificar si las direcciones de la billetera no se importaron así. Vamos a crear este método. Dentro del cuerpo if utilizará el método import addresses para importar las direcciones solo si no se importaron antes. Vamos a implementar el método de dirección importante. Obtendremos las direcciones importadas usando el nodo recibido por dirección cliente. Así que vamos a inyectarlo en esta clase. Después llamaremos al método de direcciones de lista. Al pasar los siguientes parámetros el resultado se convertirá en una secuencia y se utilizará el método map para extraer todas las direcciones de direcciones de nodo. Luego convertiremos el resultado en un conjunto de direcciones usando el método collect. A continuación, convertiremos las direcciones de monedero en un conjunto como este. Ahora, al usar el método de eliminación en las direcciones de la billetera, eliminará todas las direcciones importadas de la misma. Por último, vamos a devolver las direcciones de la billetera es llamada método vacío. Si el resultado es verdadero, ya se importaron todas las direcciones de monedero. Oh, nos olvidamos de eliminar esta línea. Vamos a hacerlo. Ahora. Vamos a la prueba de enviar Bitcoin. A partir de ahora, agregaremos algunas afirmaciones con respecto a la función de billetera de carga a algunas pruebas. Entonces si encontramos algún bug en el proceso, los corregiremos. Empecemos con la primera prueba de envío de Bitcoin. Eliminemos esta línea en su lugar. Agreguemos una llamada al método de billetera de carga de peso. Mediante este método se intentará hacer que esta prueba se ejecute más rápido. Vamos a crearlo en la clase de prueba GUI. Aquí, llamemos al método de la oblea. Pasando estos parámetros. En cada iteración de esta devolución de llamada se utilizará el método sleep para esperar 1 s. Luego comprobaremos si se establece la primera dirección actual de la billetera. Entonces, vamos a inyectar la cartera actual en esta clase. Usando la lista de nodos, el cliente verificará si el nodo cargó la dirección con la primera dirección de billetera actual. Entonces, vamos a inyectar este servicio en esta clase. Con este código se esperará hasta que el nodo cargue la cartera. Ahora, arreglemos un problema que puede causar fallas en las pruebas a veces. Aquí, el parámetro de tamaño total esperado es igual a la suma del índice de iteración actual más uno. Ahora vamos a crear la última variable de dirección de recepción que establecerá su valor a la dirección de recepción presente en la ventana. Ahora, vamos a establecer algunas otras variables que nos ayudarán a comparar los valores en la cartera antes y después de que la carguemos. Primero, el tamaño de la tabla de transacciones. A continuación, la primera fila saldo de la tabla de transacciones. Ahora llamemos al método load wallet, pasando el nombre de wallet como parámetro. Vamos a establecer esta variable aquí. Ahora, estableceremos la tabla de transacciones después de la variable de carga. Lo obtendremos usando el método de búsqueda tal como antes de cargarlo. Después haremos clic en la pestaña de direcciones y estableceremos la tabla de direcciones después de variable de carga de la misma manera. A continuación, haremos clic en la pestaña Recibir y estableceremos la última dirección de recepción, la variable de postcarga y el texto de la etiqueta después de la variable de carga. Ahora en el bloque de entonces, eliminemos estas dos líneas. Y comparemos las últimas variables de dirección receptora antes y después de cargar la billetera. Entonces vamos a establecer aquí el tamaño de la tabla de direcciones y las variables balanceadas de la tabla de direcciones de primera fila. Y agreguemos estas dos comparaciones que son iguales a las que acabamos de eliminar. Ahora, comparemos los tamaños de las tablas de direcciones antes y después de cargar la billetera. Y hagamos lo mismo con el balance de la primera fila de la tabla de direcciones. Ahora vamos a eliminar estas dos líneas, sustituyéndolas por las siguientes líneas, que hacen las mismas comparaciones pero utilizan las variables re-factorizadas. Y agreguemos las siguientes comparaciones de las variables antes y después de cargar la billetera. Comentemos todas las demás pruebas en este archivo. Y vamos a ejecutar la prueba restante. La prueba falló porque la última dirección de recepción antes y después de cargar la billetera son diferentes. En el siguiente video, lo arreglaremos. 71. 69 Cartera de carga parte 4 skillshare 2: En este video, solucionaremos el error de tener diferentes direcciones de recepción antes y después de cargar una billetera. Ocurre porque estamos usando los UTXOS para actualizar el índice de direcciones de recepción actual. Después de cargar la billetera y recuperar la billetera UTXOS, las salidas antiguas utilizadas para actualizar la dirección de recepción ya no forman parte del conjunto UTXO porque ya estaban gastadas. Así, la dirección receptora termina por no actualizarse. Lo arreglaremos transfiriendo el código responsable de actualizar las direcciones de recepción del servicio de actualización de direcciones de billetera actual a una nueva clase. La Nueva Clase usaremos las transacciones recuperadas del nodo que contiene todas las direcciones de billeteras utilizadas para actualizar las direcciones de recepción actuales. Así que vamos a crear esta clase que se llamará actualizar billetera actual recibiendo dirección su servicio en el paquete de servicios punto GUI. Agreguemos aquí la anotación de servicio. Ahora, copiemos y peguemos algún código del servicio de actualización de direcciones de billetera actual a esta clase. Vamos a agregar esta anotación calificador. Ahora vamos a crear el método de actualización aquí. Tomará una lista de transacciones de nodos. Usando el método map obtendrá un flujo de direcciones del flujo de transacciones de nodo. Después filtraremos la transmisión para que contenga solo direcciones en la billetera actual. Entonces llamaremos a la marca se usa método en cada dirección. Tomemos este método del servicio de actualización de direcciones de billetera actual. Ahora llamaremos al método actual de tipos get addressed wallet . Vamos a crear este método. Devolverá el resultado de llamar al método de direcciones get addressed types. Devolverá un conjunto de tipos de direcciones. Vamos a crear este método en la clase addresses. Aquí simplemente devolverá el conjunto de claves del campo de direcciones. Ahora para cada tipo de dirección, llamaremos al método de dirección de recepción de actualización. Para ello cambiará el tipo de este parámetro de método a tipo de dirección. Y vamos a eliminar esta línea ya que ya no vamos a necesitar. Ahora, vayamos al servicio de actualización de direcciones de billetera actual para eliminar el mismo código que pegamos a nuestra nueva clase y sus usos. Ahora, vayamos al servicio de actualización UTXOS. Inyectemos el servicio de actualización de direcciones de recepción de billetera actual en esta clase. Y llamemos al método de actualización desde el servicio inyectado pasando las transacciones de nodo como su parámetro. Ahora vamos a la prueba de enviar Bitcoin. Agreguemos la llamada al método sleep aquí para evitar una nueva condición de carrera que puede suceder a veces asegura de que su nodo esté funcionando. Y hagamos esta prueba. Se solucionó el problema de la dirección de recepción, pero la prueba falló debido a otro error. El saldo de la transacción después de cargar una billetera no es el calculado incorrectamente. Arreglemos esto. Para resolver este error, tenemos que entender mejor cómo funciona la API de transacciones de lista Bitcoin Core. Aquí está la documentación de la lista transacciones bitcoin Core API. Observe que por cada transacción, la API devuelve solo un campo de dirección. El monto se refiere únicamente a la cantidad de Bitcoin enviada a esa dirección sea negativa si no pertenece a nuestra billetera y positiva en caso contrario. Si la transacción tiene un resultado de cambio, la API devuelve más de un registro por cada transacción. Cada registro con un campo de dirección de la salida de la transacción. Veamos un ejemplo del resultado de esta API para una transacción enviada desde nuestra billetera con una entrada y dos salidas. Para la misma transacción, la API devolvió tres registros. Podemos ver que se refieren a la misma transacción mirando sus ID de transacción. Observe que los dos primeros registros tienen la misma dirección. Estos registros se refieren a la salida de cambio. El primero tiene una cantidad positiva indicando que es una dirección perteneciente a nuestra billetera. Esa es la cantidad de cambio. El segundo registro tiene la misma cantidad, pero como negativo. Eso significa que nuestras billeteras enviaron una cantidad a esa dirección. También tiene una comisión negativa, que es la tarifa de transacción que pagamos en la transacción. Si sumamos el monto de los dos primeros registros, terminamos con cero, que es exactamente el saldo que pagamos nosotros mismos en la transacción. Por último, el tercer registro contiene una cantidad negativa que indica que enviamos Bitcoin a esa dirección. También tiene una cuota igual a la tasa en el segundo registro. Considerando cómo funciona esta API, la forma correcta de calcular el saldo de la transacción es sumar los montos de registro devueltos por la misma transacción y la tarifa de una de esas registra, la transacción balanceada antes cargar una billetera es correcta porque la estamos calculando de una manera que toma en consideración la segunda transacción construida antes de enviarla a nuestro nodo. Después de cargar nuestra billetera, perdemos la información de transacción que no la está considerando para calcular el saldo de la transacción. Entonces, vayamos al servicio de transacciones Update Current Wallet para solucionar el problema. Nuestra nueva solución ya no necesitará este filtro. Entonces, eliminemos esta línea en su lugar. Agreguemos una llamada al método collect como su parámetro. Llamaremos a los colectores agrupando por método, pasando una referencia al nodo Transacción TX ID con este código se obtendrá un mapa donde las claves serán los ID de transacción y los valores serán listas de transacciones de nodo con el mismo ID de transacción. Llamemos al método values en el resultado que al método stream para obtener un flujo de listas de transacciones de nodo con el mismo T XID. El resto de este método se queda tal cual. Vamos a crear la transacción a partir del método. Tomará una lista de transacciones de nodo y devolverá una fila de transacciones. Movamos este método aquí. Primero consigamos la tarifa de transacción. Lo tomará de una corriente sin comisiones de transacción. Vamos a crear el campo de tarifa en la transacción del nodo. Después filtraremos la corriente por tarifas nominales. Luego llamaremos primero a la multa para que se devuelvan los primeros y usaremos el método de las URL para devolver cero si no se encuentra tarifa. Ahora, calculemos la cantidad. Usando el método map obtendrá un flujo que contiene todos los montos de transacción de nodo del flujo de transacciones de nodo. Luego usaremos el método reducido, pasando la referencia del método de suma decimal grande a algunas cantidades totales. Finalmente, usaremos el método o else para devolver cero sin que se encuentren transacciones. Ahora vamos a copiar y pegar esta línea aquí. Usaremos el ID de TX de transacción del primer nodo como el primer parámetro de la instanciación de la fila de transacción. A continuación, agregaremos la tarifa de transacción obtenida al monto y pasaremos el monto como parámetro aquí. Finalmente, pasaremos confirmación de transacción del primer nodo en tiempo como los parámetros de instanciación de la última fila de transacción . Eliminemos este método ya que ya no lo necesitaremos. Volvamos a ejecutar esta prueba de enviar Bitcoin. Pasó la primera prueba, pero la segunda falló debido a una condición de carrera. Vamos a arreglarlo rápidamente con el método sleep call aquí. Haremos una mejor solución para este error en el siguiente video. Por ahora, vamos a comentar esta línea para ejecutar sólo la calificación de prueba fallida . La prueba ha pasado. Vamos a descomentar el resto de la prueba. 72. 70 cartera de carga parte 5 skillshare 2 1: En este video, agregaremos más aserciones de prueba para verificar si podemos cargar correctamente una billetera con más direcciones generadas que el número inicial de direcciones generadas config. Pero primero, vamos a optimizar un método de prueba para evitar algunas condiciones de carrera en algunas pruebas. En la clase de prueba de enviar Bitcoin. Eliminemos estas dos llamadas al método de suspensión ya que nuestro fijo manejará mejor las condiciones de la carrera después de que enviemos bitcoins. Vamos a la clase de prueba GUI. Agreguemos este parámetro opcional en el método send Bitcoin and wait con el valor predeterminado igual a la dirección de recepción del hashtag. Entonces agreguemos lo siguiente y condición a este valor de retorno. Con este código solo dejaremos de esperar si el campo de dirección de recepción es diferente a la variable address. Por lo tanto, evitamos el error de enviar Bitcoins a la misma dirección dos veces secuencialmente. Ahora, vayamos a la prueba de recibir Bitcoin. En la última prueba de esta clase, agregaremos algunas aserciones para probar si podemos cargar correctamente una billetera con más direcciones generadas que el número inicial de direcciones generadas config. Así que vamos a establecer la billetera llamada variable y sustituir el parámetro en el método correcto para esta variable. Ahora llamemos aquí al método de la billetera de carga de peso y eliminemos las llamadas al método sleep de esta prueba. Ahora, después de recibir Bitcoins siete veces, fijemos la última variable de dirección de recepción al valor presente en el campo de dirección de recepción. Ahora, copiemos esta línea en la prueba de Bitcoin arena y péguela aquí. Cambiemos esta variable para abordar su vista de tabla. Hagamos lo mismo con esta otra línea. Ahora, copiemos y peguemos todas estas líneas desde la prueba de enviar Bitcoin hasta nuestra prueba. También copiemos y peguemos esta línea en nuestra nueva prueba para comparar la última dirección de recepción antes y después de cargar la billetera. Agreguemos esta línea para comparar el tamaño de la tabla de transacciones antes y después de cargar la billetera. Esta línea, haremos lo mismo con el tamaño de la tabla de direcciones. Y esta otra línea comparará el texto de la etiqueta antes y después de cargar la billetera. Vamos a ejecutar nuestro nodo. Comentemos las otras pruebas de esta clase y ejecutemos nuestra nueva prueba. La prueba ha fallado debido a la diferencia entre la última dirección de recepción antes y después de cargar la billetera. Además, si notaste el número de direcciones en la tabla de direcciones después de la carga, solo son tres cuando la correcta sería siete. Esto se debe a que no estamos guardando el número de direcciones generadas después de generarlas. Arreglemos esto. Vamos a la actualización actual del servicio de direcciones de recepción de billetera necesitará el repositorio de billeteras aquí. Así que vamos a inyectarlo en esta clase. Ahora, llamaremos al método de incremento del número de direcciones generadas en el repositorio de billetera. Como sus parámetros pasarán el número inicial de direcciones generadas y el nombre de la billetera actual. Vamos a crear este método. Cambiemos este parámetro de tipo a la clase entera y este nombre de parámetro a incrementar. Como su nombre indica, este método incrementará el número de direcciones generadas en nuestro monedero. Para hacer eso. Vamos a agregarle la anotación transaccional. Esta anotación es un requisito de la biblioteca JPA porque hará la operación SQL en dos pasos. Agreguemos también la anotación modificadora. Esta anotación es necesaria por métodos de repositorio que modifiquen registros y tablas, que es el caso. Por último, agreguemos la anotación de consulta a este método. Esta anotación indicará la operación SQL que queremos realizar como su parámetro. Vamos a agregar la siguiente cadena. Esta instrucción similar a SQL agregará al número de direcciones generadas, el valor de incremento pasado como primer argumento al método anotado. La cláusula where hará que esta operación ocurra sólo en la cartera con el nombre igual al parámetro name. Para vincular los parámetros del método a las variables SQL. Agreguemos estas dos anotaciones de poemas a estos parámetros. Ahora volvamos a hacer nuestra prueba. Genial, ha pasado. Nuestra función de billetera de carga está hecha. Ahora, es importante ejecutar todas nuestras pruebas de aplicación para verificar si apareció un error. Pero primero, arreglaremos una optimización de algunas de nuestras pruebas para usar el método de billetera de carga de peso y eliminar algunas llamadas al método de suspensión que ya no son necesarias. Primero infrecuentes estas pruebas. Y hagamos las optimizaciones mencionadas. En las pruebas de segmento anidado, como las de esta clase, debemos agregar algunos parámetros para enviar Bitcoin y wait method call. Entonces hagámoslo. El último parámetro de estas llamadas debe ser la cadena hashtag segmento anidado dirección de recepción. En algunos métodos como este, también necesitamos establecer el ID más uno es el tercer argumento de la llamada al método send Bitcoin y wait. Ahora, podemos ejecutar todas nuestras pruebas de aplicación. Todos deben pasar en mi máquina. Están tardando media hora. Entonces dejé esto como ejercicio para el alumno. 73. 71 Habilidad de la cartera de importación 2: En este video, implementaremos la capacidad de importar una billetera con la semilla mnemotécnica. Es importante tener esta opción para recuperar tu billetera y los casos en los que pierdes, destruyes o no tienes acceso al hardware o archivos que contienen la aplicación o que contienen la aplicación o base de datos con los datos de tu billetera. En estos casos, simplemente ingresaría su semilla respaldada y opcionalmente su frase de contraseña en la función de importación de la aplicación para volver a acceder a su billetera. Una cosa más, no te restringirán a recuperar tu billetera. Mediante esta aplicación, podrás utilizar semillas mnemotécnicas generadas por esta aplicación para recuperar tu wallet y otras billeteras compatibles con BIP 39. Además, podrás recuperar el acceso a tus direcciones de monedero Bitcoin importando tu semilla mnemotécnica BIP 39 esta aplicación tu semilla mnemotécnica BIP 39 generada por otras billeteras . Solo asegúrate de que ambas aplicaciones sean compatibles los pads de derivación de las direcciones que quieres importar. Entonces comencemos por crear la prueba de monedero de importación. Extenderá la clase de prueba GUI. Copiemos este código de la prueba de enviar Bitcoin y pegarlo aquí. Ahora vamos a crear una prueba llamada debería importar billetera y recibir Bitcoin. En el bloque de un solo bloque, vamos a establecer la variable monedero con nombre. Y vamos a crear una semilla mnemónica usando el método de creación del servicio de semillas mnemotécnicas. Ahora llamemos al método import wallet, pasando como parámetros el nombre de la billetera y la semilla mnemotécnica. Vamos a crear este método. También agreguemos una contraseña como tercer parámetro opcional a este método. Aquí haremos clic en un menú con la importación de texto. Después haremos clic en el elemento Menú con la billetera de texto. Ahora, haremos clic en el componente con un ID FX del nombre de la billetera. Este componente será un campo de entrada donde ingresaremos el nombre de la billetera importada. A continuación, llamaremos al método write pasando la variable name como parámetro para escribir el nombre en ese campo. A continuación, haremos clic en el campo de contraseña, que tendrá un ID FX de contraseña de billetera. Después escribiremos la contraseña en ese campo. A continuación, haremos clic en el campo de semillas mnemotécnicas y escribiremos la variable semilla mnemónica en ese campo. Por último, haremos clic en el botón Bien. También agreguemos llamada al método dormido para esperar a que se cargue la billetera. Volviendo a la prueba de monedero de importación usando el método de búsqueda, recuperemos el valor de dirección presente en el campo de dirección de recepción. Usando el método send Bitcoin and wait, enviemos 1,000 Satoshi's a la dirección recuperada. Ahora haremos clic en la pestaña de direcciones. Después usando el método de búsqueda, obtendremos la tabla de direcciones y la almacenaremos en una variable. Haremos clic en la pestaña de transacciones, obtendremos la tabla de transacciones y la almacenaremos en una variable. Además, hagamos lo mismo con el saldo total etiquetado como texto. Ahora, vamos a establecer dos variables para almacenar el tamaño de la tabla de direcciones y el tamaño de la tabla de transacciones. Agreguemos las siguientes aserciones en ese entonces bloque para verificar si las variables previamente establecidas tienen los valores esperados. Ahora vamos a duplicar esta prueba. Vamos a renombrarlo a debería importar billetera usada y bloque recibido. En esta prueba crearemos una billetera y recibiremos Bitcoins en ella antes de importar la billetera, luego importaremos la billetera, generaremos un bloque en nuestra nota y verificaremos si la aplicación se carga correctamente y actualiza la cartera importada. Así que vamos a crear un bloque dado aquí donde crearemos una billetera y le enviaremos un Bitcoin. Ahora, eliminemos esta línea. Cambiemos el nombre de esta variable para importar el nombre de la billetera y aumentemos su número con nombre de billetera. Usaremos esta variable para nombrar la cartera importada, ya que no podemos crear dos billeteras con el mismo nombre. Pasemos la variable de contraseña a esta llamada al método. Después de importar la billetera, generemos un bloque. Para ello, primero vamos a generar una dirección de nota usando el nodo obtener nueva dirección cliente. Entonces llamamos al método generate to address, pasando la dirección del nodo como su parámetro para generar un bloque. Ahora, llamemos al método del sueño para esperar a que se minara el bloque. Por último, cambiemos el saldo total esperado. Se espera un saldo de un Bitcoin confirmado y cero Bitcoin no confirmado. El resto de la prueba se queda tal cual. Ahora. Vamos al patio de recreo punto FXML para diseñar el menú de funciones de importación. Duplicemos la etiqueta del menú de carga y su contenido. Cambiemos este atributo de texto para importar. Este fx ID para importar el menú FXML. También agreguemos aquí el atributo action con su valor refiriéndose al método open-end port wallet dialogue creará este método más adelante para responder a un clic en este elemento del menú abriendo un ventana de diálogo. Vayamos al Scene Builder para ver cómo se ve. Bien, se agregó el menú Importar junto al menú de carga. Ahora vamos a copiar y pegar este código en la ventana principal FXML. Vamos a crear este método en el controlador de ventana principal. Su código será muy similar al método de diálogo open create wallet. Así que vamos a copiarlo y pegarlo aquí. Cambiemos el título del diálogo para importar billetera. Y sustituyamos el campo de diálogo de billetera de carga por el campo de diálogo de billetera de importación aquí. Vamos a crear este campo y vamos a inyectarlo en esta clase. La anotación de valor aquí apuntará al diálogo de importación de billetera FXML. Ahora vamos a crear la entrada mientras un diálogo FXML en el paquete FXML. Usemos el contenido del diálogo create wallet FXML como base para construirlo. Ahora cambiemos el texto del encabezado del diálogo. En lugar de hacer clic en Crear, solicitemos al usuario que ingrese una semilla mnemotécnica válida. A continuación, cambiemos el controlador FX para importar el controlador de diálogo de billetera. Ahora, vamos al Scene Builder. Eliminemos el botón Crear. Pongamos aquí una etiqueta y cambiemos su texto a la fecha de creación. Agreguemos un control de selección de fecha a la celda. Hagamos clic en el área de texto inicial mnemotécnico y hagamos que sea editable. Volver al editor de texto. Cambiemos este nombre de Fxi de toilette y este fx ID por contraseña de billetera. Vamos a establecer el ID de FX del picker de fecha a la fecha de creación. Ahora vamos a crear el controlador de diálogo de monedero de importación en el paquete de controladores. Vamos a agregarle la anotación de componente. Vamos a agregar todos estos campos FXML al controlador. Hagamos todos estos campos privados. Y vamos a agregarles la anotación FXML. Vamos a copiar y pegar el método inicializado desde el controlador de diálogo create wallet a nuestro nuevo controlador. Y hagamos lo mismo con que se cumplan todos los insumos requeridos. Cambiemos esta variable de nombre a nombre de billetera. También copiemos y peguemos este método a nuestra nueva clase. En el manejador de eventos del botón Okay llamaremos al método import wallet. Este método simplemente creará una Billetera utilizando el tipo de datos por parte del usuario. Así que usemos el método create wallet del controlador de diálogo create wallet como base para construirlo. Inyectemos el servicio create wallet en esta clase. Cambiemos estas variables por las de este Controlador. Y vamos a inyectar el número inicial de direcciones generadas en esta clase. Hagamos lo mismo con este campo de contexto. Ahora, en lugar de usar una nueva fecha como parámetro de este método, llamará al método de fecha de factura. Vamos a crear este método. Usaremos la siguiente lógica aquí. Si el usuario no elige una fecha, usaremos la fecha en la que Bitcoin comenzó a funcionar. Si él elige, entonces usaremos la fecha elegida. El parámetro de fecha definirá hasta qué punto en el pasado iremos el nodo para encontrar información sobre las direcciones de monedero importadas. Cuanto más viejo sea el estado, más tardará el nodo en importar la billetera. Entonces usemos el método de fecha predeterminado para definir la fecha predeterminada. Aquí usaremos el objeto de formato de fecha simple con el siguiente parámetro. Después intentaremos devolver la llamada al método de análisis de formato de fecha simple pasando la constante de fecha predeterminada como su parámetro. Usaremos el bloque catch para envolver la excepción de análisis en una excepción de tiempo de ejecución. Definamos esta constante, que es la fecha en la que Bitcoin comenzó a funcionar. Aquí. Si la fecha de creación no es nula, entonces redefinimos la variable de fecha al siguiente valor. Por último, devolvemos la fecha. Después de crear el monedero se publicará el evento monedero importado. Vamos a crearlo en el paquete GUI dot events. Aquí, pasaremos este parámetro al súper constructor, y estableceremos el campo wallet al parámetro wallet. Vamos a crear un getter para este campo. Ahora, vayamos al oyente de Save wallet. Este oyente responderá a eventos de billeteras importadas para guardar billeteras importadas. Vamos a refactorizarlo para que pueda escuchar más de un evento. Para ello, vamos a eliminar esta declaración implementos. Cambiemos este método llamado a evento de billetera no creado. Vamos a agregarle la anotación del oyente de eventos. Ahora vamos a crear el método de evento de billetera sin importancia, pasando el evento de billetera importado como su parámetro. Vamos a copiar y pegar esta línea aquí. Y agreguemos la anotación del oyente de eventos a este método. Establecer una anotación de orden para los métodos anotados del oyente de eventos hará que el orden de ejecución de estos oyentes sea predecible. Cuanto menor sea el parámetro de anotación de orden, mayor será la prioridad para que se ejecute este oyente en comparación con otros oyentes del mismo evento. Entonces agreguemos esta anotación a este método. Pasemos cero como parámetro para hacer de este oyente el primero de su tipo en ejecutarse, agreguemos la misma anotación al método de evento wallet no creado. Priorizamos guardar la billetera primero después su creación para garantizar que si los oyentes posteriores fallan, al menos guardamos sus datosPrimero. Ahora vamos al oyente de importación de billetera creado. Queremos que este oyente importe la billetera importada al nodo Bitcoin. Entonces, vamos a duplicar el método de evento de billetera descargada. Cambiemos su nombre a evento de billetera sin importancia y hagamos que sea excepto el evento apropiado. Ahora agreguemos la anotación de orden a estos métodos. Los oyentes de eventos de billetera importados y creados recibirán uno como sus parámetros y el oyente de eventos de billetera cargado cero. De esta manera, garantizamos que cuando la billetera intente recuperar datos del nodo, ya será importada por el nodo. Ahora, vayamos al oyente de billetera cargado y agreguemos un método de escucha para el evento de billetera importado, como acabamos de hacer en la clase anterior. Ahora agreguemos una anotación de orden a ambos métodos, pasando como parámetro para el método de evento de billetera sin importancia y uno para el método de evento de billetera descargada para hacer que estos oyentes se ejecuten después todos los demás por sus eventos. Ahora, vamos a ejecutar nuestro nodo. Y hagamos esta prueba. Pasó la primera prueba, pero la segunda falló. Veamos por qué. Bien, se produjo una excepción de violación de restricción porque intentamos guardar una billetera con el mismo nombre dos veces. Olvidamos cambiar la variable de nombre de billetera en la llamada de método de billetera de importación para la variable de nombre de billetera de importación. Arreglemos esto y volvamos a ejecutar la prueba defectuosa. Genial, Ha pasado. 74. 72 Validar la habilidad de la cartera 2: En este video, implementaremos algunas validaciones antes crear carteras de importación e intentar enviar transacciones. La primera validación evitará que la creación de la billetera continúe si el nombre de la billetera es igual a uno creado previamente. Entonces vayamos a la prueba de crear billetera para crear una prueba para esta condición. Se llamará no se debe crear cartera con nombre repetido. Vamos a crear una billetera en el bloque dado, creando las variables necesarias y usándolas en el método create wallet. En el bloque de un solo bloque, agreguemos algún código para crear una billetera con el mismo nombre la creada en el bloque dado, pero ahora usando la GUI. Después de intentar crear la billetera, agreguemos aquí la llamada al método dormido, esperamos que la aplicación muestre una ventana de diálogo de alerta que contenga un mensaje que diga el nombre de la billetera ya existe. Así que definamos una variable que contenga el mensaje. Ahora, usaremos el método de búsqueda para obtener un componente con ese mensaje y almacenarlo en la variable de consulta de nodo. Finalmente, haremos clic en el botón Bien para cerrar la ventana de diálogo. En el bloque de entonces. Agreguemos la siguiente comparación para verificar si el mensaje en la ventana de diálogo de alerta es igual a la variable de mensaje de error. Ahora, vayamos al controlador de diálogo create wallet. En el método create wallet, usaremos una declaración if con un servicio de validación de billetera para verificar si el nombre de la billetera es válido. Entonces, vamos a inyectar este servicio en esta clase. Vamos a crear este servicio y el paquete de servicios punto base de datos. Y terminemos de inyectarlo en esta clase. En la sentencia if, vamos a llamar al método wallet exists en él, pasando el texto del nombre como su parámetro. Vamos a crear este método. Usaremos el servicio de error de alerta y el cuerpo if. Así que vamos a inyectarlo en esta clase. Ahora, llamaremos al método alert error en él como su parámetro. Pasemos esta constante. Vamos a crear esta constante en la clase de mensajes de error. Tendrá el mismo texto que definimos en la prueba. Importemos aquí esta constante y llamemos a la declaración return. Ahora, vayamos al servicio de validar monedero. En el monedero existe el método liderará el repositorio de billeteras. Así que vamos a inyectarlo en esta clase. Ahora, devolveremos la llamada al método exists by name en él, pasando el nombre de la billetera como su parámetro. Vamos a crear este método solo por este método firma Spring Data JPA magic ya sabe cómo consultar la información deseada de la base de datos. Vayamos a la prueba de crear billetera. Comentemos estas pruebas. Ejecuta nuestro nodo y ejecuta nuestra nueva prueba. Genial, La prueba ha pasado. Vamos a descomentar estas pruebas. Ahora, agreguemos la misma validación del nombre de billetera en la función de billetera de importación. Así que vamos a copiar esta prueba y pegarla aquí en la prueba de monedero de importación. Cambiemos su nombre a no debe importar cartera con nombre repetido. Hagamos algunas adaptaciones a esta prueba. Primero, aumentemos el número de billetera con nombre. Entonces vamos a modificarlo para importar aquí una billetera en lugar de crearla. Y cambiemos los parámetros de estas llamadas a métodos. Ahora, vayamos al controlador de diálogo create wallet y copiemos este bloque si aquí. Y vamos a pegarlo aquí en el controlador de diálogo de billetera. Inyectemos los servicios necesarios a esta clase. Cambiemos esta variable por nombre de billetera. Ahora, comenten estas pruebas y ejecutemos nuestra nueva prueba. Grado. La prueba ha pasado. Vamos a descomentar estas pruebas. Ahora, agreguemos una validación de dirección. Al intentar enviar transacciones. Actualmente, podemos escribir cualquier cosa en el campo de dirección a enviar. Si intentamos enviar una transacción a una dirección no válida y se produce un error y su ignorado silenciosamente por la aplicación sin que el usuario se dé cuenta, implementará una validación que hará aparecerá un cuadro de diálogo de alerta en la pantalla si la dirección a enviar no es válida. Primero, vayamos a la prueba de enviar Bitcoin para crear una prueba para este escenario. Digamos que no debería enviar Bitcoin a una dirección inválida. Agreguemos código para crear una Billetera usando la GUI y el bloque de viento. Esperemos a la creación de la cartera. Ahora, copiemos y peguemos este código aquí para enviar fondos a la billetera. Vamos a crear esta variable de cantidad anterior aquí y establecer su valor en 0.1. Vamos a establecer uno al segundo método range llamado parámetro. Ahora vamos a crear una dirección de nodo y generar un bloque para ello. Demos clic en la pestaña Enviar y llamemos al método send Bitcoin para intentar enviar 0.01 Bitcoin a la dirección para enviar variable. Dado que la variable dirección a enviar contendrá direcciones no válidas, esperamos que aparezca una ventana de diálogo de alerta que contenga un mensaje que diga la dirección a enviar no es válida. Así que vamos a crear una variable de mensaje de error con el siguiente mensaje. Ahora, usaremos el método de búsqueda para obtener un componente con ese mensaje y almacenado en la variable de consulta de nodo. Finalmente, haremos clic en el botón Bien para cerrar la ventana de diálogo. Después bloqueemos, agreguemos la siguiente comparación para verificar si el mensaje en la ventana de diálogo de alerta es igual a la variable de mensaje de error. Definamos la dirección a enviar variable con algunos casos de prueba en el bloque where. Aquí, pasemos estos casos de prueba disponibles en la página Proyecto y Recursos. Cada caso de prueba tiene un error. Las diferentes partes del código detectarán. El primer caso de prueba es una cadena con un prefijo inexistente. El segundo caso tiene un prefijo de prueba de registro correcto, pero una dirección no válida restante. Las siguientes tres direcciones serían direcciones de prueba reg válidas, pero sus últimos caracteres fueron cambiados. Durante la construcción de direcciones. Parte de la dirección utiliza el resto de la dirección para ser construida. Esa parte es la suma de comprobación de dirección y su función es detectar alteraciones de dirección. Durante la decodificación de direcciones, se verifica la suma de comprobación y esperaríamos que ocurriera un error si esta verificación falla. Las últimas tres direcciones son válidas, pero no son del entorno de prueba reg, por lo que deben considerarse inválidas. Vayamos al buscador de configuración del script. En la llamada al método de lanzamiento de URL, pasemos una lambda cuyo cuerpo devolverá una nueva excepción de transacción de creación con una constante de dirección no válida de la clase de mensajes de error. La excepción de creación de transacción ya se captura más adelante en el código y su mensaje ya se muestra en una ventana de diálogo de alerta. Vamos a crear esta constante en la clase de mensajes de error. Tendrá el mismo texto que definimos en la prueba. Con esta modificación, esperamos que la validación cubra direcciones con prefijos no válidos. Ahora, vayamos al servicio de creadores de transacciones. Envolvamos el código en el método de salida de compilación en un bloque try-catch. En el bloque catch lanzará la excepción de creación de transacción pasando la constante de dirección no válida. Con esta modificación, esperamos que la validación cubra los errores de las direcciones de decodificación en las que falla la verificación de la suma de comprobación. Vamos a la prueba de enviar Bitcoin. Ahora, comenten estas pruebas y ejecutemos nuestra nueva prueba. Los últimos tres casos de prueba fallaron. Nuestra billetera logró enviar fondos a estas direcciones. Esto sucedió porque la decodificación de direcciones descarta los prefijos de dirección. Por supuesto, las transacciones se enviaron únicamente en el entorno de prueba reg. Por lo tanto, hacer que estas direcciones no sean válidas es importante para evitar situaciones en las que creas que estás ejecutando tu billetera en un entorno, pero en realidad se está ejecutando en otro. Arreglemos esto. Vamos a la clase de matcher de direcciones. Vamos a crear estos métodos de segmento. Devolverá un predicado de cadena. Y va a tomar un ambiente suficiente como su parámetro. Ahora, crearemos un objeto de mapa con entornos como claves y predicados de cadenas como valores. Usaremos el mapa del método para crear este mapa. Para cada entorno se establecerá un Lambda para validar si el parámetro address tiene el prefijo esperado para ese entorno. Para las direcciones de red principales de segue, esperamos que no comiencen con BCR y comiencen con BC direcciones de red de prueba BC. Empezaremos con las pruebas TB y reg. Comenzaremos con BCR t Luego devolvemos la llamada al método map.get pasando el entorno como su parámetro. Ahora, vamos a duplicar este método y cambiar su nombre a su segmento anidado. En este caso, podrán las direcciones netas. Comenzaremos con tres pruebas, direcciones de prueba net y reg. Empezaremos con dos. Duplicemos este método y cambiemos su nombre a sus direcciones de red principales heredadas. Empezaremos con uno. Pruebe las direcciones de prueba net y reg. Empezaremos con M o N. Ahora, eliminemos estas Lambdas de esta clase. Ahora vamos a la clase de configuración de direcciones. Agreguemos este campo de entorno de Bitcoin. Agreguemos aquí una anotación de valor para inyectar el valor de este campo usando la configuración de propiedades de punto de la aplicación de entorno Bitcoin . Ahora cambiemos el parámetro de segmento aquí para llamarlo como método y pasar el campo de entorno Bitcoin como su parámetro. Hagamos lo mismo con estos parámetros de segmento anidado aquí. Ahora, vayamos a la clase de configuración del script. Haremos la misma modificación que acabamos de hacer en la clase de configuración de direcciones. Inyectemos el entorno de Bitcoin en esta clase y modifiquemos los beans de configuración del script para llamar a los métodos adecuados del comparador de direcciones. Ahora, antes de volver a ejecutar nuestra nueva prueba, arreglemos algunas pruebas. En la prueba del generador secuencial de direcciones, debemos establecer el entorno Bitcoin en la instanciación de configuración de direcciones así. Vamos a ejecutar esta prueba. Genial, sigue pasando. Ahora, hagamos lo mismo con la prueba del servicio de creación de billetera. Bien, sigue pasando. Hagamos lo mismo con el único sorteo aleatorio de una prueba de selector de monedas. Esta vez, tenemos que establecer el entorno Bitcoin en la configuración del script en. Vamos a ejecutarlo. Genial, sigue pasando. Ahora, arreglemos la prueba de servicio de creadores de transacciones. Bien, sigue funcionando. Por último, hagamos lo mismo fijado en la prueba de la calculadora de tamaño de transacción. Pero esta vez tenemos que establecer los entornos Bitcoin para probar net. Ya que utilizamos direcciones netas de prueba en esta prueba, grado, las pruebas han pasado. Ahora vamos a la prueba de enviar Bitcoin. Comentemos estos casos de prueba para ejecutar sólo los tres últimos. Vamos a ejecutarlo. Genial, las pruebas han pasado. Vamos a descomentar estas pruebas. Y arreglemos esta prueba con nombre de letra. Se envía, no se envía. 75. 73 skillshare de barra de progreso 2: En este video, agregaremos una sección de pie de página a la ventana principal de nuestra aplicación. El pie de página contendrá una barra de progreso y una etiqueta de texto. La barra de progreso estará activa cuando nuestra billetera se comunique con nuestro nodo, lo que a veces puede tomar un tiempo. La etiqueta de texto mostrará una breve descripción de la actividad que está realizando nuestra billetera durante esa comunicación. Así que diseñemos esa sección en el patio de recreo punto FXML. Vayamos al Scene Builder. Primero. Agreguemos una caja H en la parte inferior de la ventana principal. Cambiemos el ancho de pref de la caja H a 600 y la altura de pref a 19. Ahora agreguemos una barra de progreso al cuadro H. También le agreguemos una etiqueta. Estableceremos el margen izquierdo de la etiqueta en diez, y su texto en una cadena vacía. Ahora en el editor de texto, vamos a copiar este código aquí y pegarlo en la ventana principal punto FXML. Ahora vamos a encapsular la barra de progreso y los componentes etiquetados en archivos FXML. Primero, vamos a crear la barra de progreso FXML. Eliminemos este contenido. Vamos a crear una etiqueta raíz ética con un tipo apuntando a la barra de progreso clase Java FX. Ahora vamos a copiar los atributos de la etiqueta y el punto de ventana principal FXML y pegarlos en nuestro nuevo FXML. Vamos a establecer esta etiqueta XML NSF X en la ventana principal, FXML. Eliminemos esta barra de progreso en su lugar. Agreguemos la etiqueta del controlador de barra de progreso, que se creará más adelante. Ahora, vamos a crear un archivo FXML de punto de pie de página para encapsular la etiqueta de etiqueta. Eliminemos este código. Vamos a copiar y pegar el código de etiqueta de la etiqueta de la ventana principal FXML al nuevo FXML. Cambiemos la etiqueta de etiqueta a una etiqueta raíz ética con un tipo apuntando a la clase etiquetada Java FX. Agreguemos este atributo XML NSF x a la nueva etiqueta. Ahora agreguemos las importaciones faltantes a este archivo. De vuelta a la ventana principal. Sustituyamos la etiqueta de etiqueta copiada por la etiqueta del controlador de pie de página. Ahora vamos a crear el controlador de barra de progreso e importado aquí. Hagamos lo mismo con el controlador de pie de página. Ahora, vayamos al controlador de barra de progreso. Vamos a agregarle la anotación de componente. Usemos el constructor del controlador de pestañas Recibir como base para construir el constructor del controlador de barra de progreso. Fijemos su nombre y anotación de valor para apuntar a las correctas. Y eliminemos la cartera actual ya que no la vamos a necesitar. Ahora, vamos a copiar este constructor y pegarlo en el controlador de pie de página. Arreglemos el nombre del constructor, y agreguemos la anotación del componente a esta clase. Hagamos que la anotación de valor apunte al FXML correcto. Ahora hagamos que esta clase extienda la clase label. Y la clase de controlador de barra de progreso extenderá la clase de barra de progreso. Vamos a la clase de escucha GUI y agreguemos ambos controladores al conjunto para que se configuren como componentes personalizados. Ahora, vamos a crear un observable que modele el estado de progreso. Será la clase de progreso asíncrono creada en el paquete observables. Vamos a agregarle una anotación de componente. Para definir el estado de la barra de progreso se creará un campo de propiedad doble llamado progreso. Vamos a instanciarlo aquí con un nuevo objeto simple double property usando cero como parámetro. Posteriormente, el parámetro cero, que establece el estado de la barra de progreso en inactivo, se pasará a la barra de progreso. Ahora vamos a crear el campo de descripción de la tarea. Será una propiedad de cadena y definiremos el texto de la etiqueta de pie de página. Vamos a instanciarlo usando una nueva propiedad de cadena simple. Vamos a crear getters para ambas propiedades. El IDE creó dos getters para cada campo, uno para la propiedad y el otro para el valor de la propiedad necesitará solo los getters para las propiedades. Entonces, eliminemos a los otros captadores. Ahora, vamos a crear el método start aquí. Lo usaremos para establecer el valor de progreso a la constante de progreso indeterminada. El valor de esta constante hará que la barra de progreso muestre una barra moviéndose hacia la izquierda y hacia la derecha, indicando que alguna tarea se está ejecutando en segundo plano. Definamos también el método stop, que volverá a establecer el valor de progreso en cero. Por lo que la barra de progreso estará inactiva, indicando que ninguna tarea se está ejecutando en segundo plano. Por último, vamos a crear el método de descripción de la tarea establecida. Tomará una cadena como su parámetro. Y establecerá el parámetro description en el campo de descripción de la tarea. Ahora para controlar cuándo cambian la barra de progreso y la etiqueta del pie de página, usaremos un aspecto. Vamos a crear la clase de aspecto de progreso en el paquete de servicios de puntos GUI. En Bota Primavera. Y el aspecto es un modificador de método. Usaremos un aspecto para definir que cada método anotado con una anotación específica iniciará la barra de progreso para encontrar el texto y la etiqueta del pie de página, ejecutar el código en el método y revertir el estado de la barra de progreso y etiquetar. Para ello, agreguemos las anotaciones de aspecto y componente a esta clase. Inyectemos el progreso asíncrono observable en esta clase. Ahora vamos a crear el método activate barra de progreso. Devolverá un objeto. Vamos a agregar la anotación around a este método ya que su parámetro pasará una cadena con el texto en la anotación, abrir paréntesis, activar barra de progreso, cerrar paréntesis. Esta anotación define que el aspecto ejecutará código antes y después de que se modifique los métodos. El parámetro activate barra de progreso, definiremos que el aspecto modificará métodos anotados con una anotación con ese nombre. Ahora, agreguemos dos parámetros a este método. El primero será el punto de unión anterior, que será un manejador para el método anotado. El segundo será la barra de progreso de activar, que dará acceso a los parámetros de anotación. Así que vamos a crear esta anotación, crearemos en un nuevo paquete de anotaciones GUI. Para que sea una anotación, debemos modificar esta palabra clave a una interfaz. Vamos a agregar la anotación de destino a este archivo ya que su parámetro pasará la constante del método. Esto hará que la anotación sea válida solo en métodos, no clases o campos. También agreguemos la anotación de retención pasando la constante de tiempo de ejecución como su parámetro. Esto hará que esta anotación esté activa en tiempo de ejecución. Finalmente, agreguemos el campo de valor de cadena a esta anotación. Este campo se rellenará con el parámetro pasado a esta llamada de anotación. Volver a la clase de aspecto de progreso. Aquí dentro de una plataforma ejecutar más tarde, la llamada al método pasará una lambda cuyo cuerpo llamará al método asincrónico de descripción de tareas de conjunto de progreso, pasando el valor de la barra de progreso activate ya que su parámetro también llame al método de inicio de progreso asíncrono aquí. Ahora llamaremos al anterior método join point proceed y storage return object en la variable result. El método proceed hará que el método anotado se ejecute y devolverá su resultado. Ahora envuelto en una plataforma ejecutar más tarde, el método cambiará nuevamente los estados de los campos de progreso asíncrono. Pero esta vez estableceremos la descripción de la tarea una cadena vacía y llamaremos al método stop en el progreso asíncrono. Finalmente, vamos a devolver la variable resultado que contiene el método anotado objeto devuelto. Ahora vamos al controlador de barra de progreso. Inyectemos el progreso asíncrono observable en esta clase. Se vinculará el campo de progreso de progreso asincrónico a esta propiedad de progreso de controladores en el método inicializado. Vamos al controlador de pie de página. Inyectemos el progreso asíncrono observable en esta clase. En el método inicializado vinculará el campo de descripción de tarea de progreso asíncrono a esta propiedad de texto de controladores. Ahora, para que la barra de progreso funcione, tenemos que anotar los métodos que queremos para rastrear el progreso con la anotación de activar barra de progreso. Hagámoslo primero en el servicio de monedero de importación. Pasemos la cadena con la cartera de carga de textos como su parámetro. Copiemos esta anotación y péguela aquí en el método de firmar y enviar del servicio de transacción sin. Cambiemos su parámetro a la transacción de envío. También agreguemos esta anotación al método de actualización de clases de servicio utxOS update como su parámetro. Pasemos la frase actualizando UTXOS. Ahora, vamos a ejecutar nuestro nodo. Y ejecutemos la prueba heredada de enviar Bitcoin para verificar la barra de progreso en acción. Como hemos visto, la barra de progreso y la etiqueta de pie de página están funcionando según lo previsto. Genial. 76. 74 Actualización de dependencias skillshare: En este video, actualizaremos las dependencias de nuestro proyecto. Mantener las dependencias de un proyecto actualizadas es una buena práctica. Al hacerlo, nos beneficiamos de errores y correcciones de vulnerabilidades de seguridad aplicadas a nuestras dependencias, manteniendo nuestra aplicación más segura. Así que vamos al archivo palm dot xml aumentará la versión de nuestras dependencias obsoletas. Dependiendo de cuándo los estés actualizando, posible que haya versiones más nuevas disponibles. Aumentemos la versión parental de arranque Spring Boot. Para mí, la versión más reciente es 2.7. 0.5 aumentará la versión Java a 19. Eliminemos ahora esta versión maravillosa, ya que ya no es necesaria, su versión se configurará automáticamente. Vamos a la configuración de la estructura del proyecto. Actualicemos la versión Java de los proyectos. Si lo necesitas, la versión Java no está disponible. Puede hacer clic en agregar SDK para descargarlo. Vamos a establecer el nivel de idioma del proyecto a lo último disponible. Ahora, aumentemos la versión de los controles Java FX. Hagamos lo mismo con el JavaFX FXML. Ahora, actualicemos el plugin Java FX Maven y el plugin G Maven para que sean correctos. Actualicemos la versión Bitcoin Java a 0.4, 0.4 en la configuración del complemento de dependencia de Maven. Ahora vamos a hacer clic en el botón Cargar cambios de Maven. Ahora vamos a actualizar la versión Bitcoin Core Node a 23. Descarguémoslo del sitio web Bitcoin core.org. Descarguemos la versión 23 e instalémosla en la misma carpeta que la versión anterior. Ya lo hice, así que me saltaré esta parte. Ahora. Asegúrese de establecer el indicador de entorno de prueba reg en el archivo bitcoin.com. Antes de ejecutar nuestro nodo, eliminemos las carpetas de prueba de registro dentro de la carpeta Bitcoin sin datos y la carpeta de la base de datos de nuestra aplicación. Lo haremos solo para limpiar nuestro entorno de prueba. Ahora, vamos a ejecutar nuestro nodo mirando la consola. Observe que nuestro nodo está ejecutando la versión 23. Bueno. Ahora, debemos hacer una pequeña modificación para nuestro monedero funcione correctamente con la nueva versión Bitcoin Core Node. Pasemos a la documentación del método RPC create wallet para entenderlo mejor. En Bitcoin Core versión 23, el argumento descriptores del método create wallet RPC por defecto es true, mientras que en la versión anterior se fijó en false. Eso hace que nuestra cartera de aplicaciones no pueda llamar a algunos métodos RPC que usamos para solucionarlo, configurará manualmente en false para que el cambio ya no nos afecte. Así que vamos al nodo crear cliente wallet. Agreguemos aquí los siguientes parámetros. Vamos a agregarlos a la firma del método create wallet. Además, el parámetro de claves privadas deshabilitadas será un booleano y definirá si la billetera de nodo creada generará claves privadas. Cuando se establece en true, el parámetro blank crea una billetera de nodo sin semillas y claves. Los conjuntos de contraseñas y frase de contraseña opcional para cifrar el NerdWallet. Como su nombre indica, el parámetro de evitar reutilización define una política para evitar la reutilización de direcciones. Finalmente, el parámetro descriptores define si el monedero de nodo creado es un monedero descriptor. Un monedero descriptor es un nuevo tipo de billetera en el Bitcoin Core Node que no usaremos. Ahora, vayamos a la carga del nodo o creamos el servicio de monedero. Vamos a agregar estas variables a esta llamada de método. Ahora vamos a copiar este código y el nodo crear cartera cliente y pegarlo aquí. Ahora vamos al servicio de monederos. Vamos a agregar los siguientes valores a esta llamada al método. Aquí, estableceremos las claves privadas deshabilitadas y los parámetros en blanco en true. Desde nuestra aplicación, mientras que no va a requerir el nodo para crear claves privadas y semillas para nosotros. La frase de contraseña será una cadena vacía. Estableceremos el parámetro de evitar reutilización en false, ya que nuestro nodo generará direcciones para nosotros y el parámetro descriptores será falso. Ahora, vayamos a la clase de prueba GUI. En esta llamada al método, vamos a pasar los siguientes valores. A diferencia del caso anterior, esta vez, queremos generar claves privadas y semillas porque usaremos el monedero de nodo para enviar bitcoins en nuestras pruebas. Por lo tanto, los dos primeros parámetros serán falsos. El tercero será una cadena vacía. El parámetro de evitar reutilización se establecerá en true. Por lo que el nodo evitará reutilizar direcciones para nuestro monedero de prueba y el argumento descriptores será falso. Ahora hagamos una modificación más por alguna razón después actualizar nuestras dependencias cuando haya dos botones bien en la pantalla durante algunas pruebas, test FX termina haciendo clic en el incorrecto. Para solucionarlo, vamos al error de alerta o servicio. Se agregará un Fx ID al botón OK de alerta mediante programación. Para hacerlo, vamos a crear la variable ok. aquí. Usaremos el método de búsqueda para obtener la referencia del botón y asignarla a la variable ok. así. Después configuraremos el ID para alertar. Bien. Ahora vayamos a la prueba de crear billetera. En esta prueba, en lugar de llamar al método click on con el parámetro okay, pasemos una referencia al botón Okay del diálogo de alerta usando su ID. Ahora, esta prueba hará clic inequívocamente en el botón correcto ok. Hagamos lo mismo con todas las demás pruebas con el mismo problema en el proyecto. Arreglemos el que está en la prueba de monedero de importación. Ahora, hagámoslo en la prueba de segue anidada de enviar Bitcoin. Por último, arreglemos las pruebas y la prueba de enviar Bitcoin. Ahora, como ejercicio, dejaré que el alumno ejecute todas las pruebas de aplicación. 77. 75 skillshare de Mainnet: En este video, instalaremos y ejecutaremos nuestra aplicación en el entorno de red principal. Ya que trataremos con dinero real, es muy recomendable que garantice que todas las pruebas de aplicación están pasando. Además, es recomendable comenzar a jugar con pequeñas cantidades de Bitcoin. Primero, actualicemos la biblioteca Bitcoin Java a la versión 0.4, 0.5 en el archivo POM. Esta versión soluciona un problema al importar el archivo de lista de palabras al ejecutar la aplicación después de instalarla. Vayamos al servicio de semillas mnemotécnicas y eliminemos esto arroja declaraciones ya que ya no lo necesitamos. Hagamos lo mismo con este método create mnemonic seed en el controlador de diálogo create wallet. Ahora, vamos a ejecutar nuestro nodo en el entorno de red principal. Para hacerlo, vamos a nuestro archivo bitcoin.com y eliminemos la línea de configuración de prueba reg, guardemos el archivo y ejecutemos el nodo Bitcoin. Bien, ahora nuestro nodo se está ejecutando en el entorno de red principal. Aquí viene la parte triste. Puede tardar días o semanas en sincronizar nuestra nota en el entorno de red principal ya que, por el momento, tiene 436 gb de tamaño. En mi caso, la consola indica que el progreso de la descarga de blockchain es de aproximadamente 52%. Más adelante en este video, te mostraré la aplicación se ejecuta en mi otra máquina, que ya se ha sincronizado por completo. Por ahora, modifiquemos nuestra aplicación para ejecutarla en el entorno de red principal. En el archivo de propiedades del punto de la aplicación, modifiquemos el entorno de Bitcoin configurando dos redes principales. Asignaremos el puerto 83 32 a la nota RPC URI config. Este es el puerto predeterminado que utiliza el nodo Bitcoin para exponer su API RPC en la red principal. A continuación, vamos a establecer la clave crypt en la configuración de URL de fuente de datos de primavera a esta variable de entorno que nos requiere establecer esta variable de entorno en nuestro sistema operativo antes de compilar nuestro código. Al hacerlo, aumentamos la seguridad de nuestra aplicación, evitando exponer las variables de la base de datos en nuestro código. Hagamos lo mismo con los valores de las configuraciones de nombre de usuario y contraseña de Spring Data Source. Ahora vamos a generar valores seguros para estas configuraciones. Para ello, usemos el administrador de bases de datos SQL lo logrará llamando así a la función de clave cripta. Vamos a generar tres valores y copiarlos y pegarlos en un archivo de texto. Es importante que mantengas estos valores en un lugar seguro ya que cualquier cambio en estos valores antes de compilar nuevamente la aplicación resultará en la pérdida de acceso a la base de datos. Si eso sucede, seguirás teniendo acceso a tu billetera. Si guardas tus billeteras, semilla mnemotécnica y contraseña, pero tendrás que eliminar los archivos de la base de datos y volver a compilar la aplicación. Ahora, voy a pegar estos valores de variables de entorno directamente en las propiedades de punto de la aplicación pueden arreglar. Lo estoy haciendo porque al menos en mi máquina Windows, la aplicación no interpola estos valores con el entorno del sistema. Uno, el mismo problema no ocurre en Linux. Entonces creo que es algún tipo de error extraño durante la compilación. Dime en la sección de comentarios si experimentaste el mismo problema. Para que podamos encontrar una solución para este problema juntos. Por ahora, podemos seguir adelante con la aplicación dot properties is, is in the Maven tab. Hagamos clic derecho en el botón Instalar. Haga clic en modificar configuración de ejecución. En la pestaña corredor. Activemos la casilla de verificación skip tests para que el comando Maven install no ejecute las pruebas de la aplicación antes de instalar la aplicación. Si está utilizando versiones más recientes de IntelliJ AID, esta opción puede estar disponible en el icono de configuración en esta ventana. Haga clic en el botón Bien. Ahora, haga doble clic en la opción de instalación personalizada dentro de la sección Ejecutar configuración. Genial, la aplicación se instaló con éxito dentro de la carpeta indicada en la consola. Antes de ejecutarlo, asegúrese de instalar el SDK de Java con la misma versión que la aplicación. Iré al sitio web de Oracle para descargarlo e instalarlo. Después de instalarlo, cierre y abra el terminal. Ahora, copia la ruta donde tu aplicación instaló el archivo JAR de la aplicación. Puede usar el comando java space double hyphen version para asegurarse de que su terminal ejecute la versión correcta de Java. Ahora ejecuta el comando java space, hyphen jar space, la ruta que acabas de copiar. Genial, la aplicación comenzó con éxito en el entorno de red principal. Intentemos crear una nueva cartera. Creó con éxito una nueva billetera, pero como nuestro nodo aún se está hundiendo, la barra de progreso de carga permanecería activa durante mucho tiempo antes de que pudiéramos probarla. Ahora, voy a mostrar la billetera trabajando en el entorno de red principal en mi máquina Linux donde el nodo está 100% sincronizado. Así que acabo de instalar la aplicación de la misma manera que lo hicimos para Windows. Esto muestra una gran ventaja de Java, que es la suave compatibilidad multiplataforma. Ejecutemos la aplicación. A partir de ahora, voy a ocultar algunos datos que verás en la pantalla por motivos de privacidad. Primero, cargo una billetera. Ya lo creé correctamente cargado como se esperaba. Ahora, voy a crear una cartera nueva. Anotaré la semilla mnemotécnica usando pluma y papel antes de hacer clic en el botón Aceptar. Ahora, voy a copiar la dirección y pegarla en un editor de texto. Ahora, cargaré la cartera anterior, que tiene algunos fondos en ella. Ahora vamos a enviar algunos Satoshi's a la dirección que copiamos de la tabla de direcciones. Podemos ver que una nueva dirección de cambio recibió algunos fondos. Genial. En la tabla de transacciones, vemos que se creó una nueva transacción con cero confirmación. Ahora abramos la cartera que recibió fondos. Podemos ver que tanto la tabla de direcciones como la tabla de transacciones tienen un nuevo registro que indica que hemos recibido con éxito algunos Satoshi's. Genial, todo está funcionando correctamente. 78. Clase adicional - Bitcoin Core v26: Bienvenido a nuestra primera clase extra sobre la actualización nuestra aplicación para comunicarnos con Bitcoin core versión 26. Veremos que hay muy buenas razones para estar al día con la versión más reciente del núcleo de Bitcoin. Primero, visitemos este sitio web para descargar Bitcoin core versión 26. Haga clic en la versión apropiada para su sistema operativo. Ya que estoy usando Windows, descargaré el archivo. Esencialmente, estaremos sobrescribiendo la versión actual del núcleo de Bitcoin que tenemos Asegúrese de elegir la misma ruta de instalación que nuestra actual. En mi caso, no procederé con la instalación ya que ya la tengo. Pero para ti, debería ser tan sencillo como hacer clic en el siguiente botón varias veces antes de ejecutar la versión recién instalada. Exploremos los beneficios inmediatos que ofrece, comenzando con la versión 25 del núcleo de Bitcoin. Podemos ver en sus notas de lanzamiento que implementa un nuevo índice que acelera significativamente los escaneos de billetera Re. Para optar por este nuevo filtro, simplemente agregamos el filtro de bloque equivale a una configuración a nuestro archivo de configuración de Bitcoin. Al reiniciar el nodo, comenzará a construir este nuevo índice Puede tardar unas horas en completarse, pero después notaremos que cargar una billetera después de algún tiempo sin ejecutar nuestro nodo se vuelve mucho más rápido Ahora vamos a discutir algunos cambios introducidos en las notas de la versión 26. Encontramos que para usar billeteras no descriptoras, necesitamos establecer una configuración RPC obsoleta en nuestro archivo de configuración Posteriormente, las billeteras no descriptoras quedarán desuso en futuras versiones principales. No te preocupes. Demostraremos cómo migrar nuestra aplicación a billeteras descriptoras en la siguiente clase extra Por ahora, para asegurarnos de que nuestras billeteras actuales funcionen con la versión 26 del núcleo de Bitcoin, agreguemos esta configuración a nuestro archivo de configuración de Bitcoin. Mientras que en ello, agreguemos también el filtro de bloque es igual a una configuración que discutimos anteriormente. Ahora ejecutemos nuestro nodo central de Bitcoin en el entorno de prueba reg. Casi terminamos, como siempre, con cualquier cambio significativo que hagamos en nuestra aplicación, debemos ejecutar todas nuestras pruebas para asegurarnos de que todo funcione correctamente. Ya lo hice por mi parte y descubrí que una prueba dejó de funcionar cuando se ejecutaba contra la nueva versión del núcleo de Bitcoin. Resulta que el no debería enviar Bitcoin con la prueba de contraseña incorrecta de la clase de prueba de enviar Bitcoin falló. Sin embargo, no porque la transacción se haya enviado con éxito, sino porque el error devuelto real difirió del esperado Lo depuré y descubrí que la respuesta de error que envía el núcleo de Bitcoin en la nueva versión ahora contiene un mensaje diferente, que es este Simplemente eliminamos el non desde el principio y agregamos falló al final. Ahora el mapeo entre esta respuesta de error desde el núcleo y nuestra aplicación debería ser precisa. Eso es. Ahora bien, si ejecutas nuestras pruebas, deberían pasar todas. En la siguiente clase extra, profundizaremos en qué es una billetera descriptora y cómo adaptar nuestra aplicación para crear este tipo de profundizaremos en qué es una billetera descriptora y cómo adaptar nuestra aplicación para crear este tipo de billetera. Nos vemos entonces.