{"id":95625,"date":"2022-08-02T08:28:12","date_gmt":"2022-08-02T06:28:12","guid":{"rendered":"https:\/\/rmarketingdigital.com\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/"},"modified":"2021-09-04T11:11:47","modified_gmt":"2021-09-04T09:11:47","slug":"construyendo-tu-propio-blockchain-en-javascript-parte-2","status":"publish","type":"post","link":"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/","title":{"rendered":"Building your own Blockchain in JavaScript - Part 2"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_86 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Contenidos<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#Preparar-una-billetera\" >Preparar una billetera<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#%C2%BFPara-que-sirven-las-claves-publicas-y-privadas\" >\u00bfPara qu\u00e9 sirven las claves p\u00fablicas y privadas?<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#Transacciones-y-firmas\" >Transacciones y firmas<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#Vamos-a-crear-esta-nueva-clase-de-transaccion\" >Vamos a crear esta nueva clase de transacci\u00f3n:<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#%C2%BFCual-es-el-proposito-de-las-firmas-y-como-funcionan\" >\u00bfCu\u00e1l es el prop\u00f3sito de las firmas y c\u00f3mo funcionan?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#Pruebas-de-las-carteras-y-firmas\" >Pruebas de las carteras y firmas<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#Inputs-Outputs-1-Como-se-posee-la-divisa-criptografica%E2%80%A6\" >Inputs &amp; Outputs 1: C\u00f3mo se posee la divisa criptogr\u00e1fica\u2026.<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#Inputs-Outputs-2-Procesando-la-transaccion%E2%80%A6\" >Inputs &amp; Outputs 2: Procesando la transacci\u00f3n\u2026.<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#El-Gran-Final-En-el-principio-no-habia-ninguna-moneda\" >El Gran Final (En el principio no hab\u00eda ninguna moneda):<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#Juegos-Play-to-earn\" >Juegos Play-to-earn<\/a><\/li><\/ul><\/nav><\/div>\n<div>\n<p>El objetivo de esta serie de tutoriales, es ayudarte a construir una imagen de c\u00f3mo se podr\u00eda desarrollar la tecnolog\u00eda de blockchain. Puedes encontrar la parte 1 aqu\u00ed: Construyendo tu propio Blockchain en JavaScript \u2013 Parte 1.<\/p>\n<p>En este segundo tutorial vamos a..:<\/p>\n<ul>\n<li>Crear una billetera sencilla.<\/li>\n<li>Enviar transacciones firmadas utilizando nuestra blockchain.<\/li>\n<\/ul>\n<p>Todo lo anterior resultar\u00e1 en nuestra propia moneda criptogr\u00e1fica.<\/p>\n<p>Continuando con el \u00faltimo tutorial, tenemos un Blockchain b\u00e1sico verificable. Pero actualmente nuestra cadena s\u00f3lo almacena mensajes bastante in\u00fatiles. Hoy vamos a sustituir estos datos por transacciones <em>(\u00abnuestro bloque podr\u00e1 realizar m\u00faltiples transacciones\u00bb)<\/em>, lo que nos permitir\u00e1 crear una <em>cripto-divisa<\/em> muy sencilla. Llamaremos a nuestra nueva moneda <strong>\u00abNoobCoin\u00bb.<\/strong><\/p>\n<p>Este tutorial asume que t\u00fa ha seguido el otro tutorial.<\/p>\n<p>Dependencias: Necesitar\u00e1s importar <strong>bounceycastle<\/strong> y <strong>GSON.<\/strong><\/p>\n<h3><span class=\"ez-toc-section\" id=\"Preparar-una-billetera\"><\/span>Preparar una billetera<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>En las cripto-divisas, la propiedad de la moneda se transfiere en la cadena de bloques como transacciones, los participantes tienen una direcci\u00f3n a la que se pueden enviar los fondos. En su forma b\u00e1sica las billeteras pueden simplemente almacenar estas direcciones, sin embargo, la mayor\u00eda de las billeteras tambi\u00e9n son <em>software<\/em> capaz de realizar nuevas transacciones en la <strong>Blockchain.<\/strong><\/p>\n<p>As\u00ed que vamos a crear una clase de <strong>wallet<\/strong> para mantener nuestra clave p\u00fablica y privada:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">\r\npackage noobchain;\r\nimport java.security.*;\r\n\r\npublic class Wallet {\r\npublic PrivateKey privateKey;\r\npublic PublicKey publicKey;\r\n}\r\n\r\n<\/pre>\n<h2><span class=\"ez-toc-section\" id=\"%C2%BFPara-que-sirven-las-claves-publicas-y-privadas\"><\/span>\u00bfPara qu\u00e9 sirven las claves p\u00fablicas y privadas?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Para nuestro <em>\u2018noobcoin\u2019<\/em> la clave p\u00fablica actuar\u00e1 como nuestra direcci\u00f3n. Est\u00e1 bien compartir esta clave p\u00fablica con otros para recibir el pago. Nuestra clave privada se utiliza para firmar nuestras transacciones, de modo que nadie puede gastar nuestros <em>noobcoins<\/em> m\u00e1s que el propietario de la clave privada. Los usuarios tendr\u00e1n que mantener su clave privada en secreto. Tambi\u00e9n enviamos nuestra clave p\u00fablica junto con la transacci\u00f3n y puede ser utilizada para verificar que nuestra firma es v\u00e1lida y que los datos no han sido alterados.<\/p>\n<p>Generamos nuestras claves privadas y p\u00fablicas en un <strong>KeyPair.<\/strong> Usaremos criptograf\u00eda de curvas el\u00edpticas para generar nuestros <strong>KeyPairs.<\/strong> A\u00f1adamos un m\u00e9todo <strong>generateKeyPair()<\/strong> a nuestra clase <strong>Wallet<\/strong> y llam\u00e9moslo en el <strong>constructor:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">package noobchain;\r\nimport java.security.*;\r\n\r\npublic class Wallet {\r\n\r\npublic PrivateKey privateKey;\r\npublic PublicKey publicKey;\r\n\r\npublic Wallet(){\r\ngenerateKeyPair();\r\n}\r\n\r\npublic void generateKeyPair() {\r\ntry {\r\nKeyPairGenerator keyGen = KeyPairGenerator.getInstance(\"ECDSA\",\"BC\");\r\nSecureRandom random = SecureRandom.getInstance(\"SHA1PRNG\");\r\nECGenParameterSpec ecSpec = new ECGenParameterSpec(\"prime192v1\");\r\n\/\/ Inicializar el generador de claves y generar un KeyPair\r\nkeyGen.initialize(ecSpec, random); \/\/256 bytes provides an acceptable security level\r\nKeyPair keyPair = keyGen.generateKeyPair();\r\n\/\/ Configurar las claves p\u00fablica y privada desde el keyPair\r\nprivateKey = keyPair.getPrivate();\r\npublicKey = keyPair.getPublic();\r\n}catch(Exception e) {\r\nthrow new RuntimeException(e);\r\n}\r\n}\r\n\r\n}\r\n\r\n<\/pre>\n<p>Ahora que tenemos los contornos de nuestra clase de billetera, echemos un vistazo a las transacciones.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Transacciones-y-firmas\"><\/span>Transacciones y firmas<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Cada transacci\u00f3n contendr\u00e1 una cierta cantidad de datos:<\/p>\n<ul>\n<li>La clave p\u00fablica (direcci\u00f3n) del remitente de los fondos.<\/li>\n<li>La clave(s) p\u00fablica(s) del receptor de los fondos.<\/li>\n<li>El valor\/importe de los fondos a transferir.<\/li>\n<li>Insumos, que son referencias a transacciones anteriores que prueban que el remitente tiene fondos para enviar.<\/li>\n<li>Salidas, que muestra el importe de las direcciones relevantes recibidas en la operaci\u00f3n. ( Estas salidas se refieren como entradas en las nuevas transacciones)<\/li>\n<li>Una firma criptogr\u00e1fica, que prueba que el propietario de la direcci\u00f3n es el que env\u00eda la transacci\u00f3n y que los datos no han sido modificados. (por ejemplo: impedir que un tercero modifique el importe enviado)<\/li>\n<\/ul>\n<h4><span class=\"ez-toc-section\" id=\"Vamos-a-crear-esta-nueva-clase-de-transaccion\"><\/span>Vamos a crear esta nueva clase de transacci\u00f3n:<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">import java.security.*;\r\nimport java.util.ArrayList;\r\n\r\npublic class Transaction {\r\n\r\npublic String transactionId; \/\/ este es tambi\u00e9n el hash de la transacci\u00f3n.\r\npublic PublicKey sender; \/\/ direcci\u00f3n del remitente\/llave p\u00fablica.\r\npublic PublicKey reciepient; \/\/ Direcci\u00f3n del destinatario\/clave p\u00fablica.\r\npublic float value;\r\npublic byte[] signature; \/\/\u00a0Esto es para evitar que nadie m\u00e1s gaste fondos en nuestra billetera.\r\n\r\npublic ArrayList inputs = new ArrayList();\r\npublic ArrayList outputs = new ArrayList();\r\n\r\nprivate static int sequence = 0; \/\/\u00a0un recuento aproximado de cu\u00e1ntas transacciones se han generado.\r\n\r\n\/\/ Constructor:\r\npublic Transaction(PublicKey from, PublicKey to, float value, ArrayList inputs) {\r\nthis.sender = from;\r\nthis.reciepient = to;\r\nthis.value = value;\r\nthis.inputs = inputs;\r\n}\r\n\r\n\/\/ Calcula el hash de la transacci\u00f3n (que se utilizar\u00e1 como su Id)\r\nprivate String calulateHash() {\r\nsequence++; \/\/\u00a0aumentar la secuencia para evitar 2 transacciones id\u00e9nticas con el mismo hash\r\nreturn StringUtil.applySha256(\r\nStringUtil.getStringFromKey(sender) +\r\nStringUtil.getStringFromKey(reciepient) +\r\nFloat.toString(value) + sequence\r\n);\r\n}\r\n}\r\n<\/pre>\n<p>Tambi\u00e9n debemos crear clases vac\u00edas <strong>TransactionInput<\/strong> y <strong>TransactionOutput,<\/strong> no te preocupes, podemos rellenarlas m\u00e1s tarde.<\/p>\n<p>Nuestra clase de transacci\u00f3n tambi\u00e9n contendr\u00e1 m\u00e9todos relevantes para generar\/verificar la firma y verificar la transacci\u00f3n.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%C2%BFCual-es-el-proposito-de-las-firmas-y-como-funcionan\"><\/span>\u00bfCu\u00e1l es el prop\u00f3sito de las firmas y c\u00f3mo funcionan?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Las firmas realizan dos tareas muy importantes en nuestra blockchain: En primer lugar, permiten que s\u00f3lo el propietario gaste sus monedas; en segundo lugar, impiden que otros manipulen la transacci\u00f3n presentada antes de que se extraiga un nuevo bloque (en el punto de entrada).<\/p>\n<p>La clave privada se utiliza para firmar los datos y la clave p\u00fablica puede utilizarse para verificar su integridad.<\/p>\n<p>Por ejemplo: James quiere enviar 2 NoobCoins a Allie, as\u00ed que el software de su billetera genera esta transacci\u00f3n y la env\u00eda a los mineros para que la incluyan en el siguiente bloque. Un minero intenta cambiar el destinatario de las 2 monedas a Juan. Sin embargo, afortunadamente, James hab\u00eda firmado los datos de la transacci\u00f3n con su clave privada, permitiendo a cualquiera verificar si los datos de la transacci\u00f3n han sido cambiados usando la clave p\u00fablica de James (ya que ninguna otra persona podr\u00e1 verificar la transacci\u00f3n).<\/p>\n<p>Podemos ver (desde el bloque de c\u00f3digo anterior) que nuestra firma ser\u00e1 un mont\u00f3n de bytes, as\u00ed que vamos a crear un m\u00e9todo para generarlos. Lo primero que necesitaremos son unas cuantas funciones de ayuda en la clase <strong>StringUtil<\/strong> :<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">\/\/Aplica la firma ECDSA y devuelve el resultado ( en bytes).\r\npublic static byte[] applyECDSASig(PrivateKey privateKey, String input) {\r\nSignature dsa;\r\nbyte[] output = new byte[0];\r\ntry {\r\ndsa = Signature.getInstance(\"ECDSA\", \"BC\");\r\ndsa.initSign(privateKey);\r\nbyte[] strByte = input.getBytes();\r\ndsa.update(strByte);\r\nbyte[] realSig = dsa.sign();\r\noutput = realSig;\r\n} catch (Exception e) {\r\nthrow new RuntimeException(e);\r\n}\r\nreturn output;\r\n}\r\n\r\n\/\/Verifica una firma de cadena\r\npublic static boolean verifyECDSASig(PublicKey publicKey, String data, byte[] signature) {\r\ntry {\r\nSignature ecdsaVerify = Signature.getInstance(\"ECDSA\", \"BC\");\r\necdsaVerify.initVerify(publicKey);\r\necdsaVerify.update(data.getBytes());\r\nreturn ecdsaVerify.verify(signature);\r\n}catch(Exception e) {\r\nthrow new RuntimeException(e);\r\n}\r\n}\r\n\r\npublic static String getStringFromKey(Key key) {\r\nreturn Base64.getEncoder().encodeToString(key.getEncoded());\r\n}\r\n<\/pre>\n<p>Ahora vamos a utilizar estos m\u00e9todos de firma en nuestra clase <strong>Transaction,<\/strong> a\u00f1adiendo los m\u00e9todos <strong>generateSignature()<\/strong> y <strong>verifiySignature():<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">\/\/Firma todos los datos que no queremos que sean alterados.\r\npublic void generateSignature(PrivateKey privateKey) {\r\nString data = StringUtil.getStringFromKey(sender) + StringUtil.getStringFromKey(reciepient) + Float.toString(value) ;\r\nsignature = StringUtil.applyECDSASig(privateKey,data);\r\n}\r\n\/\/Verifica que los datos que firmamos no hayan sido alterados\r\npublic boolean verifiySignature() {\r\nString data = StringUtil.getStringFromKey(sender) + StringUtil.getStringFromKey(reciepient) + Float.toString(value) ;\r\nreturn StringUtil.verifyECDSASig(sender, data, signature);\r\n}\r\n<\/pre>\n<p>Las firmas ser\u00e1n verificadas por los mineros a medida que se a\u00f1ada una nueva transacci\u00f3n a un bloque.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Pruebas-de-las-carteras-y-firmas\"><\/span>Pruebas de las carteras y firmas<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Ahora estamos casi a mitad de camino probemos algunas cosas que est\u00e1n funcionando. En la clase <strong>NoobChain<\/strong> agreguemos algunas variables nuevas y reemplacemos el contenido de nuestro m\u00e9todo principal:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">import java.security.Security;\r\nimport java.util.ArrayList;\r\nimport java.util.Base64;\r\nimport com.google.gson.GsonBuilder;\r\n\r\npublic class NoobChain {\r\n\r\npublic static ArrayList blockchain = new ArrayList();\r\npublic static int difficulty = 5;\r\npublic static Wallet walletA;\r\npublic static Wallet walletB;\r\n\r\npublic static void main(String[] args) {\r\n\/\/Configurar el castillo de Bouncey como un proveedor de seguridad\r\nSecurity.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());\r\n\/\/Crear las nuevas carteras\r\nwalletA = new Wallet();\r\nwalletB = new Wallet();\r\n\/\/Probar claves p\u00fablicas y privadas\r\nSystem.out.println(\"Claves privadas y p\u00fablicas:\");\r\nSystem.out.println(StringUtil.getStringFromKey(walletA.privateKey));\r\nSystem.out.println(StringUtil.getStringFromKey(walletA.publicKey));\r\n\/\/Crear una transacci\u00f3n de prueba de WalletA a WalletB\r\nTransaction transaction = new Transaction(walletA.publicKey, walletB.publicKey, 5, null);\r\ntransaction.generateSignature(walletA.privateKey);\r\n\/\/Verificar el funcionamiento de la firma y verificarla desde la clave p\u00fablica\r\nSystem.out.println(\"Se verifica la firma\");\r\nSystem.out.println(transaction.verifiySignature());\r\n\r\n}\r\n<\/pre>\n<h3><span class=\"ez-toc-section\" id=\"Inputs-Outputs-1-Como-se-posee-la-divisa-criptografica%E2%80%A6\"><\/span>Inputs &amp; Outputs 1: C\u00f3mo se posee la divisa criptogr\u00e1fica\u2026.<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Para que t\u00fa tengas un (1) bitcoin, tiense que recibir 1 Bitcoin. El libro mayor no le agrega realmente una moneda de bitcoin y menos una moneda de bitcoin del remitente, el remitente hace referencia a que \u00e9l\/ella recibi\u00f3 previamente una moneda de bitcoin, entonces se cre\u00f3 una salida de transacci\u00f3n que muestra que 1 Bitcoin fue enviado a su direcci\u00f3n. (Las entradas de transacci\u00f3n son referencias a salidas de transacci\u00f3n anteriores).<\/p>\n<p>El saldo de tu billetera es la suma de todas las salidas de transacciones no utilizadas dirigidas a usted.<\/p>\n<p>A partir de este punto seguiremos la convenci\u00f3n de bitcoins y llamaremos a las salidas de transacciones no utilizadas: <strong>UTXO\u2019s.<\/strong><\/p>\n<p>As\u00ed que vamos a crear una clase de entrada de transacciones:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">public class TransactionInput {\r\npublic String transactionOutputId; \/\/\u00a0Referencia a TransactionOutputs -&gt; transactionId\r\npublic TransactionOutput UTXO; \/\/\u00a0Contiene la salida de la transacci\u00f3n no utilizada\r\n\r\npublic TransactionInput(String transactionOutputId) {\r\nthis.transactionOutputId = transactionOutputId;\r\n}\r\n}\r\n<\/pre>\n<p>Y una clase <strong>TransactionOutputs:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">import java.security.PublicKey;\r\n\r\npublic class TransactionOutput {\r\npublic String id;\r\npublic PublicKey reciepient; \/\/\u00a0tambi\u00e9n conocido como el nuevo due\u00f1o de estas monedas.\r\npublic float value; \/\/\u00a0la cantidad de monedas que poseen\r\npublic String parentTransactionId; \/\/\u00a0el identificador de la transacci\u00f3n en la que se cre\u00f3 esta salida\r\n\r\n\/\/Constructor\r\npublic TransactionOutput(PublicKey reciepient, float value, String parentTransactionId) {\r\nthis.reciepient = reciepient;\r\nthis.value = value;\r\nthis.parentTransactionId = parentTransactionId;\r\nthis.id = StringUtil.applySha256(StringUtil.getStringFromKey(reciepient)+Float.toString(value)+parentTransactionId);\r\n}\r\n\r\n\/\/Comprueba si la moneda le pertenece\r\npublic boolean isMine(PublicKey publicKey) {\r\nreturn (publicKey == reciepient);\r\n}\r\n\r\n}\r\n<\/pre>\n<p>Los resultados de la transacci\u00f3n mostrar\u00e1n la cantidad final enviada a cada parte de la transacci\u00f3n. \u00c9stos, cuando se mencionan como entradas en las nuevas transacciones, act\u00faan como prueba de que tiene monedas que enviar.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Inputs-Outputs-2-Procesando-la-transaccion%E2%80%A6\"><\/span>Inputs &amp; Outputs 2: Procesando la transacci\u00f3n\u2026.<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Los bloques de la cadena pueden recibir muchas transacciones y la cadena de bloques puede ser muy, muy larga, podr\u00eda llevar eones procesar una nueva transacci\u00f3n porque tenemos que encontrar y comprobar sus entradas. Para evitar esto, mantendremos una colecci\u00f3n extra de todas las transacciones no gastadas que pueden ser utilizadas como insumos. En nuestra clase <strong>NoobChain<\/strong> agrega esta colecci\u00f3n de todos los <strong>UTXOs:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">public class NoobChain {\r\n\r\npublic static ArrayList blockchain = new ArrayList();\r\npublic static HashMap&lt;String,TransactionOutputs&gt; UTXOs = new HashMap&lt;String,TransactionOutputs&gt;(); \/\/lista de todas las transacciones no gastadas.\r\npublic static int difficulty = 5;\r\npublic static Wallet walletA;\r\npublic static Wallet walletB;\r\n\r\npublic static void main(String[] args) {\r\n<\/pre>\n<p>Ahora vamos a poner todo junto para procesar la transacci\u00f3n con un m\u00e9todo booleano <strong>processTransaction<\/strong> en nuestra Clase de <strong>Transacci\u00f3n:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">\/\/Devuelve true si se pudiera crear una nueva transacci\u00f3n.\r\npublic boolean processTransaction() {\r\n\r\nif(verifiySignature() == false) {\r\nSystem.out.println(\"#la Firma de la transacci\u00f3n no se verific\u00f3\");\r\nreturn false;\r\n}\r\n\r\n\/\/Recopilar los datos de las transacciones (aseg\u00farese de que no se hayan gastado):\r\nfor(TransactionInput i : inputs) {\r\ni.UTXO = NoobChain.UTXOs.get(i.transactionOutputId);\r\n}\r\n\r\n\/\/verificar si la transacci\u00f3n es v\u00e1lida:\r\nif(getInputsValue() &lt; NoobChain.minimumTransaction) {\r\nSystem.out.println(\"#Insumos de transacciones a peque\u00f1os: \" + getInputsValue());\r\nreturn false;\r\n}\r\n\r\n\/\/generar resultados de transacciones:\r\nfloat leftOver = getInputsValue() - value; \/\/get value of inputs then the left over change:\r\ntransactionId = calulateHash();\r\noutputs.add(new TransactionOutput( this.reciepient, value,transactionId)); \/\/enviar valor al destinatario\r\noutputs.add(new TransactionOutput( this.sender, leftOver,transactionId)); \/\/\u00a0enviar la parte de atr\u00e1s 'cambiar' de nuevo al remitente\r\n\r\n\/\/a\u00f1adir salidas a la lista de productos no utilizados\r\nfor(TransactionOutput o : outputs) {\r\nNoobChain.UTXOs.put(o.id , o);\r\n}\r\n\r\n\/\/Eliminar las entradas de transacci\u00f3n de las listas UTXO como gastadas:\r\nfor(TransactionInput i : inputs) {\r\nif(i.UTXO == null) continue; \/\/if Transaction can't be found skip it\r\nNoobChain.UTXOs.remove(i.UTXO.id);\r\n}\r\n\r\nreturn true;\r\n}\r\n\r\n\/\/devuelve la suma de los valores de las entradas (UTXOs)\r\npublic float getInputsValue() {\r\nfloat total = 0;\r\nfor(TransactionInput i : inputs) {\r\nif(i.UTXO == null) continue; \/\/Si no se encuentra la transacci\u00f3n, s\u00e1ltela.\r\ntotal += i.UTXO.value;\r\n}\r\nreturn total;\r\n}\r\n\r\n\/\/returns sum of outputs:\r\npublic float getOutputsValue() {\r\nfloat total = 0;\r\nfor(TransactionOutput o : outputs) {\r\ntotal += o.value;\r\n}\r\nreturn total;\r\n}\r\n<\/pre>\n<p>\u2026Con este m\u00e9todo realizamos algunas verificaciones para asegurarnos de que la transacci\u00f3n es v\u00e1lida, luego recogemos entradas y generamos salidas. (Ver l\u00edneas comentadas en el c\u00f3digo para m\u00e1s informaci\u00f3n).<\/p>\n<p>Es importante destacar que, hacia el final, descartamos las entradas de nuestra lista de UTXO, lo que significa que una salida de transacci\u00f3n s\u00f3lo se puede utilizar una vez como entrada\u2026 Por lo tanto, se debe utilizar el valor completo de las entradas, de modo que el remitente se devuelve a s\u00ed mismo el \u00abcambio\u00bb.<\/p>\n<p>Por fin vamos a actualizar nuestra billetera a:<\/p>\n<p>Re\u00fane nuestro balance (haciendo un bucle a trav\u00e9s de la lista de UTXOs y comprobando si la salida de una transacci\u00f3n es Mine())<br \/>\nY generar transacciones para nosotros\u2026.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">import java.security.*;\r\nimport java.security.spec.ECGenParameterSpec;\r\nimport java.util.ArrayList;\r\nimport java.util.HashMap;\r\nimport java.util.Map;\r\n\r\npublic class Wallet {\r\n\r\npublic PrivateKey privateKey;\r\npublic PublicKey publicKey;\r\n\r\npublic HashMap&lt;String,TransactionOutput&gt; UTXOs = new HashMap&lt;String,TransactionOutput&gt;(); \/\/only UTXOs owned by this wallet.\r\n\r\npublic Wallet() {...\r\n\r\npublic void generateKeyPair() {...\r\n\r\n\/\/devuelve el saldo y almacena los UTXO's propiedad de esta cartera en este.UTXOs\r\npublic float getBalance() {\r\nfloat total = 0;\r\nfor (Map.Entry&lt;String, TransactionOutput&gt; item: NoobChain.UTXOs.entrySet()){\r\nTransactionOutput UTXO = item.getValue();\r\nif(UTXO.isMine(publicKey)) { \/\/\u00a0si la salida me pertenece ( si las monedas me pertenecen)\r\nUTXOs.put(UTXO.id,UTXO); \/\/a\u00f1\u00e1dalo a nuestra lista de transacciones no gastadas.\r\ntotal += UTXO.value ;\r\n}\r\n}\r\nreturn total;\r\n}\r\n\/\/Genera y devuelve una nueva transacci\u00f3n desde esta cartera.\r\npublic Transaction sendFunds(PublicKey _recipient,float value ) {\r\nif(getBalance() &lt; value) { \/\/reunir el saldo y verificar los fondos.\r\nSystem.out.println(\"#No hay fondos suficientes para enviar la transacci\u00f3n. Transacci\u00f3n descartada.\");\r\nreturn null;\r\n}\r\n\/\/create array list of inputs\r\nArrayList inputs = new ArrayList();\r\n\r\nfloat total = 0;\r\nfor (Map.Entry&lt;String, TransactionOutput&gt; item: UTXOs.entrySet()){\r\nTransactionOutput UTXO = item.getValue();\r\ntotal += UTXO.value;\r\ninputs.add(new TransactionInput(UTXO.id));\r\nif(total &gt; value) break;\r\n}\r\n\r\nTransaction newTransaction = new Transaction(publicKey, _recipient , value, inputs);\r\nnewTransaction.generateSignature(privateKey);\r\n\r\nfor(TransactionInput input: inputs){\r\nUTXOs.remove(input.transactionOutputId);\r\n}\r\nreturn newTransaction;\r\n}\r\n\r\n}\r\n<\/pre>\n<p>A\u00f1adiendo transacciones a nuestros bloques:<\/p>\n<p>Ahora que tenemos un sistema de transacciones que funciona, necesitamos implementarlo en nuestra cadena de bloques. Deber\u00edamos reemplazar los datos in\u00fatiles que ten\u00edamos en nuestros bloques por un ArrayList de transacciones. Sin embargo, puede haber miles de transacciones en un solo bloque, demasiadas para incluirlas en nuestro c\u00e1lculo hash\u2026 pero no se preocupe, podemos usar la ra\u00edz merkle de las transacciones (puede leer r\u00e1pidamente acerca de los \u00e1rboles merkle aqu\u00ed *pronto*).<\/p>\n<p>A\u00f1adamos un m\u00e9todo helper para generar el merkleroot en StringUtils:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">\/\/Realiza una serie de transacciones y devuelve una ra\u00edz de merkle.\r\npublic static String getMerkleRoot(ArrayList transactions) {\r\nint count = transactions.size();\r\nArrayList previousTreeLayer = new ArrayList();\r\nfor(Transaction transaction : transactions) {\r\npreviousTreeLayer.add(transaction.transactionId);\r\n}\r\nArrayList treeLayer = previousTreeLayer;\r\nwhile(count &gt; 1) {\r\ntreeLayer = new ArrayList();\r\nfor(int i=1; i &lt; previousTreeLayer.size(); i++) {\r\ntreeLayer.add(applySha256(previousTreeLayer.get(i-1) + previousTreeLayer.get(i)));\r\n}\r\ncount = treeLayer.size();\r\npreviousTreeLayer = treeLayer;\r\n}\r\nString merkleRoot = (treeLayer.size() == 1) ? treeLayer.get(0) : \"\";\r\nreturn merkleRoot;\r\n}\r\n<\/pre>\n<p>Ahora vamos a implementar nuestros cambios en la clase de bloques:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">import java.util.ArrayList;\r\nimport java.util.Date;\r\n\r\npublic class Block {\r\n\r\npublic String hash;\r\npublic String previousHash;\r\npublic String merkleRoot;\r\npublic ArrayList transactions = new ArrayList(); \/\/our data will be a simple message.\r\npublic long timeStamp; \/\/como n\u00famero de milisegundos desde 1\/1\/1970.\r\npublic int nonce;\r\n\r\n\/\/Block Constructor.\r\npublic Block(String previousHash ) {\r\nthis.previousHash = previousHash;\r\nthis.timeStamp = new Date().getTime();\r\n\r\nthis.hash = calculateHash(); \/\/Making sure we do this after we set the other values.\r\n}\r\n\r\n\/\/Calcular nuevo hash basado en el contenido de los bloques\r\npublic String calculateHash() {\r\nString calculatedhash = StringUtil.applySha256(\r\npreviousHash +\r\nLong.toString(timeStamp) +\r\nInteger.toString(nonce) +\r\nmerkleRoot\r\n);\r\nreturn calculatedhash;\r\n}\r\n\r\n\/\/Aumenta el valor de nonce hasta que se alcanza el objetivo de hash.\r\npublic void mineBlock(int difficulty) {\r\nmerkleRoot = StringUtil.getMerkleRoot(transactions);\r\nString target = StringUtil.getDificultyString(difficulty); \/\/Create a string with difficulty * \"0\"\r\nwhile(!hash.substring( 0, difficulty).equals(target)) {\r\nnonce ++;\r\nhash = calculateHash();\r\n}\r\nSystem.out.println(\"Bloque minado!!! : \" + hash);\r\n}\r\n\r\n\/\/A\u00f1adir transacciones a este bloque\r\n\r\npublic boolean addTransaction(Transaction transaction) {\r\n\/\/procesar la transacci\u00f3n y verificar si es v\u00e1lida, a menos que el bloque sea un bloque de g\u00e9nesis y luego ignorar.\r\nif(transaction == null) return false;\r\nif((previousHash != \"0\")) {\r\nif((transaction.processTransaction() != true)) {\r\nSystem.out.println(\"Transaction failed to process. Discarded.\");\r\nreturn false;\r\n}\r\n}\r\ntransactions.add(transaction);\r\nSystem.out.println(\"Transacci\u00f3n a\u00f1adida con \u00e9xito al Bloque\");\r\nreturn true;\r\n}\r\n\r\n}\r\n<\/pre>\n<p>Nota que tambi\u00e9n actualizamos nuestro constructor de bloques ya que no necesitamos pasar los datos de la cadena e incluimos la ra\u00edz de <strong>merkle<\/strong> en el m\u00e9todo de c\u00e1lculo hash.<\/p>\n<p>Nuestro m\u00e9todo booleano <strong>addTransaction<\/strong> a\u00f1adir\u00e1 las transacciones y s\u00f3lo devolver\u00e1 true si la transacci\u00f3n se ha a\u00f1adido correctamente.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"El-Gran-Final-En-el-principio-no-habia-ninguna-moneda\"><\/span>El Gran Final (En el principio no hab\u00eda ninguna moneda):<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Deber\u00edamos probar el env\u00edo de monedas desde y hacia las billeteras, y actualizar nuestro control de validez de la blockchain. Pero primero necesitamos una manera de introducir nuevas monedas en la mezcla. Hay muchas maneras de crear nuevas monedas, en la cadena de bloques de bitcoin por ejemplo: los mineros pueden incluir una transacci\u00f3n para ellos mismos como recompensa por cada bloque extra\u00eddo. Por ahora, sin embargo, s\u00f3lo liberaremos todas las monedas que deseamos tener, en el primer bloque (el bloque g\u00e9nesis). Al igual que bitcoin, codificaremos el bloque g\u00e9nesis.<\/p>\n<p><strong>Vamos a actualizar nuestra clase NoobChain con todo lo que necesita:<\/strong><\/p>\n<ul>\n<li>Un bloque de Genesis que libera 100 Noobcoins a la billetera.<\/li>\n<li>Una verificaci\u00f3n de validez de cadena actualizada que tiene en cuenta las operaciones.<\/li>\n<li>Algunas transacciones de prueba para ver que todo funciona.<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">public class NoobChain {\r\n\r\npublic static ArrayList blockchain = new ArrayList();\r\npublic static HashMap&lt;String,TransactionOutput&gt; UTXOs = new HashMap&lt;String,TransactionOutput&gt;();\r\n\r\npublic static int difficulty = 3;\r\npublic static float minimumTransaction = 0.1f;\r\npublic static Wallet walletA;\r\npublic static Wallet walletB;\r\npublic static Transaction genesisTransaction;\r\n\r\npublic static void main(String[] args) {\r\n\/\/a\u00f1adir nuestros bloques a la lista ArrayList de bloques:\r\nSecurity.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); \/\/Setup Bouncey castle as a Security Provider\r\n\r\n\/\/Crear billeteras\r\nwalletA = new Wallet();\r\nwalletB = new Wallet();\r\nWallet coinbase = new Wallet();\r\n\r\n\/\/crear una transacci\u00f3n de g\u00e9nesis, que env\u00eda 100 NoobCoin a la billeteraA:\r\ngenesisTransaction = new Transaction(coinbase.publicKey, walletA.publicKey, 100f, null);\r\ngenesisTransaction.generateSignature(coinbase.privateKey); \/\/firmar manualmente la transacci\u00f3n de g\u00e9nesis\r\ngenesisTransaction.transactionId = \"0\"; \/\/configurar manualmente el ID de la transacci\u00f3n\r\ngenesisTransaction.outputs.add(new TransactionOutput(genesisTransaction.reciepient, genesisTransaction.value, genesisTransaction.transactionId)); \/\/a\u00f1adir manualmente la salida de transacciones\r\nUTXOs.put(genesisTransaction.outputs.get(0).id, genesisTransaction.outputs.get(0)); \/\/\u00a0es importante almacenar nuestra primera transacci\u00f3n en la lista de UTXOs.\r\n\r\nSystem.out.println(\"Creaci\u00f3n y explotaci\u00f3n del bloque G\u00e9nesis.... \");\r\nBlock genesis = new Block(\"0\");\r\ngenesis.addTransaction(genesisTransaction);\r\naddBlock(genesis);\r\n\r\n\/\/prueba\r\nBlock block1 = new Block(genesis.hash);\r\nSystem.out.println(\"nEl balance de WalletA es: \" + walletA.getBalance());\r\nSystem.out.println(\"nWalletA est\u00e1 intentando enviar fondos (40) a WalletB...\");\r\nblock1.addTransaction(walletA.sendFunds(walletB.publicKey, 40f));\r\naddBlock(block1);\r\nSystem.out.println(\"n el balance de WalletA es: \" + walletA.getBalance());\r\nSystem.out.println(\"El balance de WalletB es: \" + walletB.getBalance());\r\n\r\nBlock block2 = new Block(block1.hash);\r\nSystem.out.println(\"nWalletA Intentando enviar m\u00e1s fondos (1000) de los que tiene...\");\r\nblock2.addTransaction(walletA.sendFunds(walletB.publicKey, 1000f));\r\naddBlock(block2);\r\nSystem.out.println(\"nel balance de WalletA es: \" + walletA.getBalance());\r\nSystem.out.println(\"el balance de WalletB es: \" + walletB.getBalance());\r\n\r\nBlock block3 = new Block(block2.hash);\r\nSystem.out.println(\"nWalletB est\u00e1 intentando enviar fondos (20) a WalletA...\");\r\nblock3.addTransaction(walletB.sendFunds( walletA.publicKey, 20));\r\nSystem.out.println(\"nel balance de WalletA es: \" + walletA.getBalance());\r\nSystem.out.println(\"el balance de WalletB es: \" + walletB.getBalance());\r\n\r\nisChainValid();\r\n\r\n}\r\n\r\npublic static Boolean isChainValid() {\r\nBlock currentBlock;\r\nBlock previousBlock;\r\nString hashTarget = new String(new char[difficulty]).replace('', '0');\r\nHashMap&lt;String,TransactionOutput&gt; tempUTXOs = new HashMap&lt;String,TransactionOutput&gt;(); \/\/a temporary working list of unspent transactions at a given block state.\r\ntempUTXOs.put(genesisTransaction.outputs.get(0).id, genesisTransaction.outputs.get(0));\r\n\r\n\/\/a trav\u00e9s de la cadena de bloques para comprobar los hashes:\r\nfor(int i=1; i &lt; blockchain.size(); i++) {\r\n\r\ncurrentBlock = blockchain.get(i);\r\npreviousBlock = blockchain.get(i-1);\r\n\/\/comparar el hash registrado y el hash calculado:\r\nif(!currentBlock.hash.equals(currentBlock.calculateHash()) ){\r\nSystem.out.println(\"#Hashes actuales no son iguales\");\r\nreturn false;\r\n}\r\n\/\/comparar el hash anterior y el hash anterior registrado\r\nif(!previousBlock.hash.equals(currentBlock.previousHash) ) {\r\nSystem.out.println(\"#Hashes anteriores no son iguales\");\r\nreturn false;\r\n}\r\n\/\/comprobar si se ha resuelto el problema del hash\r\nif(!currentBlock.hash.substring( 0, difficulty).equals(hashTarget)) {\r\nSystem.out.println(\"#Este bloque no ha sido minado\");\r\nreturn false;\r\n}\r\n\r\n\/\/a trav\u00e9s de las transacciones de bloqueo:\r\nTransactionOutput tempOutput;\r\nfor(int t=0; t &lt;currentBlock.transactions.size(); t++) {\r\nTransaction currentTransaction = currentBlock.transactions.get(t);\r\n\r\nif(!currentTransaction.verifiySignature()) {\r\nSystem.out.println(\"#La firma en la transacci\u00f3n (\" + t + \") es inv\u00e1lida\");\r\nreturn false;\r\n}\r\nif(currentTransaction.getInputsValue() != currentTransaction.getOutputsValue()) {\r\nSystem.out.println(\"#Las entradas son iguales a las salidas en la transacci\u00f3n(\" + t + \")\");\r\nreturn false;\r\n}\r\n\r\nfor(TransactionInput input: currentTransaction.inputs) {\r\ntempOutput = tempUTXOs.get(input.transactionOutputId);\r\n\r\nif(tempOutput == null) {\r\nSystem.out.println(\"#Falta la entrada referenciada en Transacci\u00f3n(\" + t + \")\");\r\nreturn false;\r\n}\r\n\r\nif(input.UTXO.value != tempOutput.value) {\r\nSystem.out.println(\"#El valor de la entrada referenciada Transacci\u00f3n(\" + t + \") es inv\u00e1lido\");\r\nreturn false;\r\n}\r\n\r\ntempUTXOs.remove(input.transactionOutputId);\r\n}\r\n\r\nfor(TransactionOutput output: currentTransaction.outputs) {\r\ntempUTXOs.put(output.id, output);\r\n}\r\n\r\nif( currentTransaction.outputs.get(0).reciepient != currentTransaction.reciepient) {\r\nSystem.out.println(\"#El destinatario de la salida de la transacci\u00f3n (\" + t + \") no es quien deber\u00eda ser\");\r\nreturn false;\r\n}\r\nif( currentTransaction.outputs.get(1).reciepient != currentTransaction.sender) {\r\nSystem.out.println(\"#Transacci\u00f3n(\" + t + \") salida 'cambio' no es el remitente.\");\r\nreturn false;\r\n}\r\n\r\n}\r\n\r\n}\r\nSystem.out.println(\"La Blockchain es v\u00e1lida\");\r\nreturn true;\r\n}\r\n\r\npublic static void addBlock(Block newBlock) {\r\nnewBlock.mineBlock(difficulty);\r\nblockchain.add(newBlock);\r\n}\r\n}\r\n<\/pre>\n<p>Las billeteras ahora pueden enviar fondos de forma segura en tu blockchain, s\u00f3lo si tienen fondos para enviarlos. Esto significa que t\u00fa tienes tu propia criptocurrencia local.<\/p>\n<p>\u00a1Ya terminaron con las transacciones en su cadena de bloqueo!<\/p>\n<p>Has creado con \u00e9xito tu propia criptocurrencia. Tu Bockchain ahora:<\/p>\n<ul>\n<li>Permite a los usuarios crear carteras con `nueva Cartera();\u00bb.<\/li>\n<li>Proporciona carteras con claves p\u00fablicas y privadas mediante criptograf\u00eda de curvas el\u00edpticas.<\/li>\n<li>Asegura la transferencia de fondos, utilizando un algoritmo de firma digital para probar la propiedad.<\/li>\n<li>Y finalmente permitir a los usuarios hacer transacciones en su cadena de bloques con <strong>\u2018Block.addTransaction(walletA.sendFunds( walletB.publicKey, 20));\u2019;\u00bbBlock.addTransaction(walletA.sendFunds( walletB.publicKey, 20));\u2019.<\/strong><\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"Juegos-Play-to-earn\"><\/span>Juegos Play-to-earn<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<\/div>\n<p>La industria de los videojuegos est\u00e1 pasando por una fase de crecimiento intenso, y el sistema \u00abjugar para ganar\u00bb abre nuevas posibilidades para el juego con blockchain.<\/p>\n<p><strong>Los jugadores de este modelo de negocio crean valor para los desarrolladores del juego y otros jugadores al participar en la econom\u00eda del juego. Como recompensa por su participaci\u00f3n, reciben activos del juego. Estos activos van desde recursos del juego como herramientas de juego, armas o criptomonedas, hasta otros activos del juego que pueden ser tokenizados en la blockchain e incluso vendidos como NFT. Por ello, el modelo de negocio \u00abplay-to-earn\u00bb ha tenido \u00e9xito cuando se ha utilizado con juegos de blockchain. Los ingresos totales del juego \u00abplay-to-earn\u00bb, <a href=\"https:\/\/nftpeaker.com\/blockchain-gaming\/axie-infinity-hace-una-declaracion-despues-del-informe-del-gobierno\/\">Axie Infinity<\/a>, se\u00a0<a href=\"https:\/\/es.cointelegraph.com\/news\/axie-infinity-refreshes-record-high-as-axs-ascends-131-in-just-three-days\" data-amp=\"https:\/\/es-cointelegraph-com.cdn.ampproject.org\/c\/s\/es.cointelegraph.com\/news\/axie-infinity-refreshes-record-high-as-axs-ascends-131-in-just-three-days\/amp\">acercaron a los USD 120 millones<\/a>\u00a0en julio.<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>El objetivo de esta serie de tutoriales, es ayudarte a construir una imagen de c\u00f3mo se podr\u00eda desarrollar la tecnolog\u00eda de blockchain. Puedes encontrar la parte 1 aqu\u00ed: Construyendo tu&#8230;<\/p>","protected":false},"author":1,"featured_media":95626,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1374],"tags":[1414],"class_list":["post-95625","post","type-post","status-publish","format-standard","has-post-thumbnail","category-javascript","tag-criptomonedas"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.0 (Yoast SEO v28.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Construyendo tu propio Blockchain en JavaScript \u2013 Parte 2 - R Marketing Digital<\/title>\n<meta name=\"description\" content=\"El objetivo de esta serie de tutoriales, es ayudarte a construir una imagen de c\u00f3mo se podr\u00eda desarrollar la tecnolog\u00eda de blockchain. Puedes encontrar la\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Construyendo tu propio Blockchain en JavaScript \u2013 Parte 2\" \/>\n<meta property=\"og:description\" content=\"El objetivo de esta serie de tutoriales, es ayudarte a construir una imagen de c\u00f3mo se podr\u00eda desarrollar la tecnolog\u00eda de blockchain. Puedes encontrar la\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/\" \/>\n<meta property=\"og:site_name\" content=\"R Marketing Digital\" \/>\n<meta property=\"article:published_time\" content=\"2022-08-02T06:28:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/12\/decentralized-780x514-4508508.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"780\" \/>\n\t<meta property=\"og:image:height\" content=\"514\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"R Marketing Digital\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/javascript\\\/construyendo-tu-propio-blockchain-en-javascript-parte-2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/javascript\\\/construyendo-tu-propio-blockchain-en-javascript-parte-2\\\/\"},\"author\":{\"name\":\"R Marketing Digital\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#\\\/schema\\\/person\\\/7c0d9782b2977b840b3740f00c69a73e\"},\"headline\":\"Construyendo tu propio Blockchain en JavaScript \u2013 Parte 2\",\"datePublished\":\"2022-08-02T06:28:12+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/javascript\\\/construyendo-tu-propio-blockchain-en-javascript-parte-2\\\/\"},\"wordCount\":1807,\"image\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/javascript\\\/construyendo-tu-propio-blockchain-en-javascript-parte-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/decentralized-780x514-4508508.jpg\",\"keywords\":[\"Criptomonedas\"],\"articleSection\":[\"Javascript\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/javascript\\\/construyendo-tu-propio-blockchain-en-javascript-parte-2\\\/\",\"url\":\"https:\\\/\\\/rmarketingdigital.com\\\/javascript\\\/construyendo-tu-propio-blockchain-en-javascript-parte-2\\\/\",\"name\":\"Construyendo tu propio Blockchain en JavaScript \u2013 Parte 2 - R Marketing Digital\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/javascript\\\/construyendo-tu-propio-blockchain-en-javascript-parte-2\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/javascript\\\/construyendo-tu-propio-blockchain-en-javascript-parte-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/decentralized-780x514-4508508.jpg\",\"datePublished\":\"2022-08-02T06:28:12+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#\\\/schema\\\/person\\\/7c0d9782b2977b840b3740f00c69a73e\"},\"description\":\"El objetivo de esta serie de tutoriales, es ayudarte a construir una imagen de c\u00f3mo se podr\u00eda desarrollar la tecnolog\u00eda de blockchain. Puedes encontrar la\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/rmarketingdigital.com\\\/javascript\\\/construyendo-tu-propio-blockchain-en-javascript-parte-2\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/javascript\\\/construyendo-tu-propio-blockchain-en-javascript-parte-2\\\/#primaryimage\",\"url\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/decentralized-780x514-4508508.jpg\",\"contentUrl\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/decentralized-780x514-4508508.jpg\",\"width\":780,\"height\":514,\"caption\":\"decentralized-780x514-4508508-6992688-jpg\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#website\",\"url\":\"https:\\\/\\\/rmarketingdigital.com\\\/\",\"name\":\"R Marketing Digital\",\"description\":\"Agencia SEO | Publicidad redes sociales | Community Management\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/rmarketingdigital.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#\\\/schema\\\/person\\\/7c0d9782b2977b840b3740f00c69a73e\",\"name\":\"R Marketing Digital\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g\",\"caption\":\"R Marketing Digital\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Construyendo tu propio Blockchain en JavaScript \u2013 Parte 2 - R Marketing Digital","description":"The goal of this tutorial series is to help you build a picture of how blockchain technology could develop. You can find the","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/","og_locale":"en_US","og_type":"article","og_title":"Construyendo tu propio Blockchain en JavaScript \u2013 Parte 2","og_description":"El objetivo de esta serie de tutoriales, es ayudarte a construir una imagen de c\u00f3mo se podr\u00eda desarrollar la tecnolog\u00eda de blockchain. Puedes encontrar la","og_url":"https:\/\/rmarketingdigital.com\/en\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/","og_site_name":"R Marketing Digital","article_published_time":"2022-08-02T06:28:12+00:00","og_image":[{"width":780,"height":514,"url":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/12\/decentralized-780x514-4508508.jpg","type":"image\/jpeg"}],"author":"R Marketing Digital","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rmarketingdigital.com\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#article","isPartOf":{"@id":"https:\/\/rmarketingdigital.com\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/"},"author":{"name":"R Marketing Digital","@id":"https:\/\/rmarketingdigital.com\/#\/schema\/person\/7c0d9782b2977b840b3740f00c69a73e"},"headline":"Construyendo tu propio Blockchain en JavaScript \u2013 Parte 2","datePublished":"2022-08-02T06:28:12+00:00","mainEntityOfPage":{"@id":"https:\/\/rmarketingdigital.com\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/"},"wordCount":1807,"image":{"@id":"https:\/\/rmarketingdigital.com\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#primaryimage"},"thumbnailUrl":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/12\/decentralized-780x514-4508508.jpg","keywords":["Criptomonedas"],"articleSection":["Javascript"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/rmarketingdigital.com\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/","url":"https:\/\/rmarketingdigital.com\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/","name":"Construyendo tu propio Blockchain en JavaScript \u2013 Parte 2 - R Marketing Digital","isPartOf":{"@id":"https:\/\/rmarketingdigital.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rmarketingdigital.com\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#primaryimage"},"image":{"@id":"https:\/\/rmarketingdigital.com\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#primaryimage"},"thumbnailUrl":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/12\/decentralized-780x514-4508508.jpg","datePublished":"2022-08-02T06:28:12+00:00","author":{"@id":"https:\/\/rmarketingdigital.com\/#\/schema\/person\/7c0d9782b2977b840b3740f00c69a73e"},"description":"The goal of this tutorial series is to help you build a picture of how blockchain technology could develop. You can find the","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rmarketingdigital.com\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rmarketingdigital.com\/javascript\/construyendo-tu-propio-blockchain-en-javascript-parte-2\/#primaryimage","url":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/12\/decentralized-780x514-4508508.jpg","contentUrl":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/12\/decentralized-780x514-4508508.jpg","width":780,"height":514,"caption":"decentralized-780x514-4508508-6992688-jpg"},{"@type":"WebSite","@id":"https:\/\/rmarketingdigital.com\/#website","url":"https:\/\/rmarketingdigital.com\/","name":"R Digital Marketing","description":"SEO Agency | Advertising social networks | Community Management","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/rmarketingdigital.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/rmarketingdigital.com\/#\/schema\/person\/7c0d9782b2977b840b3740f00c69a73e","name":"R Digital Marketing","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g","caption":"R Marketing Digital"}}]}},"_links":{"self":[{"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/posts\/95625","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/comments?post=95625"}],"version-history":[{"count":0,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/posts\/95625\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/media\/95626"}],"wp:attachment":[{"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/media?parent=95625"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/categories?post=95625"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rmarketingdigital.com\/en\/wp-json\/wp\/v2\/tags?post=95625"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}