├── .gitignore ├── src ├── favicon.ico ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── styles.css ├── app │ ├── main.ts │ ├── about │ │ ├── about.component.ts │ │ └── about.component.html │ ├── app.component.ts │ ├── app.component.html │ ├── app.routing.ts │ ├── home │ │ ├── lesson.tokens.html │ │ ├── lesson.hash.html │ │ ├── home.component.html │ │ ├── lesson.block.html │ │ ├── lesson.thanks.html │ │ ├── lesson.blockchain.html │ │ ├── home.component.ts │ │ └── lesson.distributed.html │ └── app.module.ts ├── assets │ ├── images │ │ └── social_flat_rounded_rects_svg │ │ │ ├── license.md │ │ │ ├── Pinboard.svg │ │ │ ├── Facebook.svg │ │ │ ├── Tumblr.svg │ │ │ ├── Pocket.svg │ │ │ ├── Email.svg │ │ │ ├── LinkedIn.svg │ │ │ ├── Pinterest.svg │ │ │ ├── Twitter.svg │ │ │ ├── Google+.svg │ │ │ ├── Wordpress.svg │ │ │ └── Reddit.svg │ └── main.css ├── tsconfig.app.json ├── tslint.json ├── browserslist ├── main.ts ├── index.html └── polyfills.ts ├── docker-compose.yml ├── Dockerfile ├── .travis.yml ├── tsconfig.json ├── package.json ├── README.md ├── angular.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | dist 4 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aarroyoc/blockchain-web/master/src/favicon.ico -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | @import "assets/main.css"; -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.6" 2 | 3 | services: 4 | angular: 5 | build: . 6 | volumes: 7 | - ./build:/opt/blockchain-web/dist 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:10 2 | 3 | WORKDIR /opt/blockchain-web 4 | 5 | COPY . . 6 | 7 | RUN npm install 8 | 9 | RUN npm install -g @angular/cli@7.3.9 10 | 11 | CMD ["ng","build","--prod"] 12 | -------------------------------------------------------------------------------- /src/app/main.ts: -------------------------------------------------------------------------------- 1 | import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; 2 | import {AppModule} from './app.module'; 3 | 4 | platformBrowserDynamic().bootstrapModule(AppModule); 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8" 4 | - "10" 5 | install: 6 | - npm install 7 | before_script: 8 | - npm install -g @angular/cli 9 | script: 10 | - ng build --prod 11 | 12 | -------------------------------------------------------------------------------- /src/app/about/about.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'about', 5 | templateUrl: 'about.component.html' 6 | }) 7 | 8 | export class AboutComponent { 9 | } 10 | -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/license.md: -------------------------------------------------------------------------------- 1 | # Social Flat Rounded Rects 2 | ## by [Aha-Soft Team](http://www.aha-soft.com/free-icons/) 3 | **License:** Creative Commons (Attribution 3.0 Unported) 4 | 5 | *Dec 26th, 2014* 6 | -------------------------------------------------------------------------------- /src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "types": [] 6 | }, 7 | "exclude": [ 8 | "src/test.ts", 9 | "**/*.spec.ts" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'my-app', 5 | templateUrl: 'app.component.html' 6 | }) 7 | 8 | export class AppComponent implements OnInit { 9 | ngOnInit() { 10 | console.log('AppComponent initializing...'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tslint.json", 3 | "rules": { 4 | "directive-selector": [ 5 | true, 6 | "attribute", 7 | "app", 8 | "camelCase" 9 | ], 10 | "component-selector": [ 11 | true, 12 | "element", 13 | "app", 14 | "kebab-case" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/browserslist: -------------------------------------------------------------------------------- 1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | # For IE 9-11 support, please uncomment the last line of the file and adjust as needed 5 | > 0.5% 6 | last 2 versions 7 | Firefox ESR 8 | not dead 9 | # IE 9-11 -------------------------------------------------------------------------------- /src/app/about/about.component.html: -------------------------------------------------------------------------------- 1 |
2 |

About Page

3 |
4 |

Angular generator

5 |

Yeoman generator for scaffold out a front-end project with Angular and TypeScript.

6 |
7 | 8 |
9 |

Yeoman

10 |

The web's scaffolding tool for modern webapps.

11 |
12 |
13 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.log(err)); 13 | -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/Pinboard.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Aprende Blockchain 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Cargando Aprende Blockchain... 14 | 15 | 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "module": "es2015", 9 | "moduleResolution": "node", 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "target": "es5", 13 | "typeRoots": [ 14 | "node_modules/@types" 15 | ], 16 | "lib": [ 17 | "es2017", 18 | "dom" 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Aprende Blockchain

4 |
5 |
6 |
7 | 8 |
9 | 15 | -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/Facebook.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.routing.ts: -------------------------------------------------------------------------------- 1 | import {ModuleWithProviders} from '@angular/core'; 2 | import {Routes, RouterModule} from '@angular/router'; 3 | 4 | import {HomeComponent} from './home/home.component'; 5 | import {AboutComponent} from './about/about.component'; 6 | 7 | const appRoutes: Routes = [ 8 | { path: '', component: HomeComponent }, 9 | { path: 'about', component: AboutComponent } 10 | ]; 11 | 12 | export const appRoutingProviders: any[] = []; 13 | 14 | export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes); 15 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * In development mode, to ignore zone related error stack frames such as 11 | * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can 12 | * import the following file, but please comment it out in production mode 13 | * because it will have performance impact when throw error 14 | */ 15 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 16 | -------------------------------------------------------------------------------- /src/app/home/lesson.tokens.html: -------------------------------------------------------------------------------- 1 |

Tokens

2 |
3 |

Ya hemos visto como funcionan las blockchains distribuidas. Acerquémonos ahora un poco más a como funciona Bitcoin.

4 |

La blockchain de Bitcoin es como un libro de contabilidad, registra los movimientos de dinero, de un emisor a un receptor. En ningún momento la blockchain almacena la cantidad de dinero que tiene un usuario.

5 |

Para comprobar si se puede realizar un pago, Bitcoin mira hacia atrás en la cadena y mira cuando ha recibido dinero y cuando se lo ha gastado. No hace falta comprobar toda la cadena, con que encuentre que ha recibido una cantidad de dinero que todavía no ha gastado ya es suficiente.

6 |
7 | 8 |
9 | -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/Tumblr.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/Pocket.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/Email.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/LinkedIn.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/home/lesson.hash.html: -------------------------------------------------------------------------------- 1 |

Hash

2 |
3 |

En primer lugar vamos a ver algo muy utilizado en criptografía, los hashes. Un hash es una combinación de números y letras generada únicamente para un determinado conjunto de datos. Piensa en ello como si fuesen huellas dactilares del mundo digital.

4 |

Un hash por tanto permite identificar un conjunto de datos, ya que para un mismo conjunto de datos siempre tendremos el mismo hash. Sin embargo, si sabes el hash de unos datos es extremadamente complicado restaurar los datos originales.

5 |

En el siguiente ejemplo, vas a poder crear hashes con el algoritmo SHA-256. Adelante, escribe y borra datos y verás como el hash cambia, de manera totalmente radical. Sin embargo, si introduces exactamente los mismos datos tienes el mismo hash

6 | 9 | 10 |
11 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {BrowserModule} from '@angular/platform-browser'; 3 | import {FormsModule} from '@angular/forms'; 4 | import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; 5 | 6 | import {AppComponent} from './app.component'; 7 | import {routing, appRoutingProviders} from './app.routing'; 8 | import {HomeComponent,LessonHash,LessonBlock,LessonBlockchain,LessonDistributed, LessonTokens, LessonThanks} from './home/home.component'; 9 | import {AboutComponent} from './about/about.component'; 10 | 11 | @NgModule({ 12 | declarations: [ 13 | AppComponent, 14 | HomeComponent, 15 | AboutComponent, 16 | LessonHash, 17 | LessonBlock, 18 | LessonBlockchain, 19 | LessonDistributed, 20 | LessonTokens, 21 | LessonThanks 22 | ], 23 | imports: [ 24 | FormsModule, 25 | BrowserModule, 26 | BrowserAnimationsModule, 27 | routing 28 | ], 29 | providers: [appRoutingProviders], 30 | bootstrap: [AppComponent] 31 | }) 32 | 33 | export class AppModule { 34 | } 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blockchain-web-ng", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build" 8 | }, 9 | "private": true, 10 | "dependencies": { 11 | "@angular/animations": "^6.1.10", 12 | "@angular/common": "^6.1.10", 13 | "@angular/compiler": "^6.1.10", 14 | "@angular/core": "^6.1.10", 15 | "@angular/forms": "^6.1.10", 16 | "@angular/http": "^6.1.10", 17 | "@angular/platform-browser": "^6.1.10", 18 | "@angular/platform-browser-dynamic": "^6.1.10", 19 | "@angular/router": "^6.1.10", 20 | "core-js": "^2.6.3", 21 | "js-sha256": "^0.9.0", 22 | "rxjs": "^6.3.3", 23 | "zone.js": "^0.8.29" 24 | }, 25 | "devDependencies": { 26 | "@angular-devkit/build-angular": "^0.7.5", 27 | "@angular/cli": "^6.1.5", 28 | "@angular/compiler-cli": "^6.1.10", 29 | "@angular/language-service": "^6.1.10", 30 | "@types/node": "~8.9.4", 31 | "codelyzer": "~4.2.1", 32 | "ts-node": "~5.0.1", 33 | "tslint": "~5.9.1", 34 | "typescript": "~2.7.2" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/assets/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Cambria, Georgia; 3 | } 4 | 5 | h1 { 6 | color: #369; 7 | font-family: Arial, Helvetica, sans-serif; 8 | font-size: 250%; 9 | font-weight: bold; 10 | margin-top: 30px; 11 | margin-bottom: 22px; 12 | } 13 | 14 | a { 15 | text-decoration: none; 16 | color: #337ab7; 17 | } 18 | 19 | a:hover { 20 | text-decoration: underline; 21 | } 22 | 23 | .header-container, .main-container, .footer-container { 24 | width: 700px; 25 | margin: 0 auto; 26 | } 27 | 28 | .main-container { 29 | margin-bottom: 20px; 30 | box-shadow: 0 1px 4px 0 rgba(0,0,0,0.37); 31 | } 32 | 33 | .main-container .resource, .main-container h3 { 34 | padding: 16px 23px; 35 | } 36 | 37 | .main-container h3 { 38 | margin: 0; 39 | color: #373E41; 40 | font-size: 20px; 41 | font-weight: bold; 42 | background-color: #ECEFF1; 43 | } 44 | 45 | .main-container h4 { 46 | margin: 0; 47 | font-size: 16px; 48 | font-weight: bold; 49 | line-height: 24px; 50 | } 51 | 52 | .main-container p { 53 | margin: 0; 54 | } 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BlockchainWebNg 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.1.2. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 28 | -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/Pinterest.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/Twitter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/home/home.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Introducción

3 |
4 | 5 | 10 |

11 | Bienvenido a Aprende Blockchain. En esta página encontrarás respuestas sencillas a preguntas como:

12 | 18 |

Blockchain

19 |

Blockchain es la tecnología subyacente a inventos tan innovadores como Bitcoin o Ethereum.

20 |
21 | 22 |
23 |

Bitcoin

24 |

Bitcoin es una moneda virtual basada en Blockchain. Se implementa como un libro de contabilidad escrito en Blockchain. Su fama ya es mundial y es usada por millones de personas todos los días.

25 |
26 | Blockchain 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | 35 | 40 |
41 |
42 | -------------------------------------------------------------------------------- /src/app/home/lesson.block.html: -------------------------------------------------------------------------------- 1 |

Blocks

2 |
3 |

Los bloques son un conjunto de datos, con su correspondiente hash.

4 |

En primer lugar tenemos un número de bloque, un número nonce del que hablaremos más tarde y finalmente los datos.

5 |

Lo que hace un bloque distinto a lo que hemos visto antes es que un bloque puede ser válido o no. Un bloque es válido si su hash cumple cierta condición. En este caso, vamos a pedir que un bloque sea válido si su hash comienza por 3 ceros.

6 |

Como puedes comprobar, la probabilidad de que eso ocurra es mínima. Para ajustar el hash a la condición impuesta se usa el número nonce. En un proceso denominado minado se probarán valores de nonce hasta que el hash cumpla la condición impuesta, solo así el bloque es válido.

7 |

Observa que si cambias el valor de los datos es necesario volver a minar. En este ejemplo el minado es rápido, pero puede hacerse más lento eligiendo otras condiciones.

8 |
9 | 10 | 11 | 12 | 13 | 14 |

El bloque es válido

15 |

El bloque es inválido

16 |
17 |
18 | -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/Google+.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "blockchain-web-ng": { 7 | "root": "", 8 | "sourceRoot": "src", 9 | "projectType": "application", 10 | "prefix": "app", 11 | "schematics": {}, 12 | "architect": { 13 | "build": { 14 | "builder": "@angular-devkit/build-angular:browser", 15 | "options": { 16 | "outputPath": "dist/blockchain-web-ng", 17 | "index": "src/index.html", 18 | "main": "src/main.ts", 19 | "polyfills": "src/polyfills.ts", 20 | "tsConfig": "src/tsconfig.app.json", 21 | "assets": [ 22 | "src/favicon.ico", 23 | "src/assets" 24 | ], 25 | "styles": [ 26 | "src/styles.css" 27 | ], 28 | "scripts": [] 29 | }, 30 | "configurations": { 31 | "production": { 32 | "fileReplacements": [ 33 | { 34 | "replace": "src/environments/environment.ts", 35 | "with": "src/environments/environment.prod.ts" 36 | } 37 | ], 38 | "optimization": true, 39 | "outputHashing": "all", 40 | "sourceMap": false, 41 | "extractCss": true, 42 | "namedChunks": false, 43 | "aot": true, 44 | "extractLicenses": true, 45 | "vendorChunk": false, 46 | "buildOptimizer": true 47 | } 48 | } 49 | }, 50 | "serve": { 51 | "builder": "@angular-devkit/build-angular:dev-server", 52 | "options": { 53 | "browserTarget": "blockchain-web-ng:build" 54 | }, 55 | "configurations": { 56 | "production": { 57 | "browserTarget": "blockchain-web-ng:build:production" 58 | } 59 | } 60 | }, 61 | "extract-i18n": { 62 | "builder": "@angular-devkit/build-angular:extract-i18n", 63 | "options": { 64 | "browserTarget": "blockchain-web-ng:build" 65 | } 66 | } 67 | } 68 | } 69 | }, 70 | "defaultProject": "blockchain-web-ng" 71 | } -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/Wordpress.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "deprecation": { 15 | "severity": "warn" 16 | }, 17 | "eofline": true, 18 | "forin": true, 19 | "import-blacklist": [ 20 | true, 21 | "rxjs/Rx" 22 | ], 23 | "import-spacing": true, 24 | "indent": [ 25 | true, 26 | "spaces" 27 | ], 28 | "interface-over-type-literal": true, 29 | "label-position": true, 30 | "max-line-length": [ 31 | true, 32 | 140 33 | ], 34 | "member-access": false, 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-arg": true, 47 | "no-bitwise": true, 48 | "no-console": [ 49 | true, 50 | "debug", 51 | "info", 52 | "time", 53 | "timeEnd", 54 | "trace" 55 | ], 56 | "no-construct": true, 57 | "no-debugger": true, 58 | "no-duplicate-super": true, 59 | "no-empty": false, 60 | "no-empty-interface": true, 61 | "no-eval": true, 62 | "no-inferrable-types": [ 63 | true, 64 | "ignore-params" 65 | ], 66 | "no-misused-new": true, 67 | "no-non-null-assertion": true, 68 | "no-shadowed-variable": true, 69 | "no-string-literal": false, 70 | "no-string-throw": true, 71 | "no-switch-case-fall-through": true, 72 | "no-trailing-whitespace": true, 73 | "no-unnecessary-initializer": true, 74 | "no-unused-expression": true, 75 | "no-use-before-declare": true, 76 | "no-var-keyword": true, 77 | "object-literal-sort-keys": false, 78 | "one-line": [ 79 | true, 80 | "check-open-brace", 81 | "check-catch", 82 | "check-else", 83 | "check-whitespace" 84 | ], 85 | "prefer-const": true, 86 | "quotemark": [ 87 | true, 88 | "single" 89 | ], 90 | "radix": true, 91 | "semicolon": [ 92 | true, 93 | "always" 94 | ], 95 | "triple-equals": [ 96 | true, 97 | "allow-null-check" 98 | ], 99 | "typedef-whitespace": [ 100 | true, 101 | { 102 | "call-signature": "nospace", 103 | "index-signature": "nospace", 104 | "parameter": "nospace", 105 | "property-declaration": "nospace", 106 | "variable-declaration": "nospace" 107 | } 108 | ], 109 | "unified-signatures": true, 110 | "variable-name": false, 111 | "whitespace": [ 112 | true, 113 | "check-branch", 114 | "check-decl", 115 | "check-operator", 116 | "check-separator", 117 | "check-type" 118 | ], 119 | "no-output-on-prefix": true, 120 | "use-input-property-decorator": true, 121 | "use-output-property-decorator": true, 122 | "use-host-property-decorator": true, 123 | "no-input-rename": true, 124 | "no-output-rename": true, 125 | "use-life-cycle-interface": true, 126 | "use-pipe-transform-interface": true, 127 | "component-class-suffix": true, 128 | "directive-class-suffix": true 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/weak-map'; 35 | // import 'core-js/es6/set'; 36 | 37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 38 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 39 | 40 | /** IE10 and IE11 requires the following for the Reflect API. */ 41 | // import 'core-js/es6/reflect'; 42 | 43 | 44 | /** Evergreen browsers require these. **/ 45 | // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. 46 | import 'core-js/es7/reflect'; 47 | 48 | 49 | /** 50 | * Web Animations `@angular/platform-browser/animations` 51 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 52 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 53 | **/ 54 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 55 | 56 | /** 57 | * By default, zone.js will patch all possible macroTask and DomEvents 58 | * user can disable parts of macroTask/DomEvents patch by setting following flags 59 | */ 60 | 61 | // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 62 | // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 63 | // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 64 | 65 | /* 66 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 67 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 68 | */ 69 | // (window as any).__Zone_enable_cross_context_check = true; 70 | 71 | /*************************************************************************************************** 72 | * Zone JS is required by default for Angular itself. 73 | */ 74 | import 'zone.js/dist/zone'; // Included with Angular CLI. 75 | 76 | 77 | 78 | /*************************************************************************************************** 79 | * APPLICATION IMPORTS 80 | */ 81 | -------------------------------------------------------------------------------- /src/app/home/lesson.thanks.html: -------------------------------------------------------------------------------- 1 |

Agradecimientos

2 |
3 |

Muchas gracias por visitar esta página que explica conceptos de Blockchain

4 |

Quiero agradecer este proyecto a Anders Brownworth por su magnífica explicación

5 |

Puedes compartir la página

6 |

Si te ha servido comparte

7 | 33 | 44 |

Si quieres hacerme feliz, haz una donación

45 | 51 |
52 | -------------------------------------------------------------------------------- /src/app/home/lesson.blockchain.html: -------------------------------------------------------------------------------- 1 |

Blockchain

2 |
3 |

Blockchain, como su nombre indica, es una cadena de bloques. En una cadena de bloques, los bloques además de tener datos y nonce, poseen el hash del bloque anterior. Así se logra el encadenamiento.

4 |

Por supuesto para generar el hash de cada bloque ahora necesitamos los datos, el hash del bloque anterior y buscar el nonce adecuado.

5 |

Ahora imagina que quieres modificar un bloque. Si el bloque es el último de la cadena no hay problema, simplemente minas de nuevo y obtienes un bloque válido con su hash de 3 ceros al principio. ¿Y si quisiéras modificar un dato que no fuese el último?

6 |

Modificarías el bloque y lo minarías para obtener un hash de 3 ceros y tener un bloque válido. Sin embargo el bloque siguiente de la cadena contenía tu hash anterior, el de antes de realizar la modificación, y era vaĺido con ese valor. Ahora, al modificar el contenido del bloque anterior, su hash ha cambiado y el contenido del bloque siguiente también ha cambiado y ha dejado de ser válido. Tienes que volver a minar el bloque siguiente. Y el siguiente. Y el siguiente.

7 |

En un Blockchain modificar un bloque antiguo cuesta. Cuanto más antiguo sea el bloque (más atrás esté en la cadena), más difícil será modificar su valor. Esta es una de las bases de la inmutabilidad de Blockchain

8 |
9 |

Aquí tienes 5 bloques de un mini-blockchain. Observa que si modficas un bloque es necesario minar todos los bloques siguientes para que la cadena siga siendo válida

10 |
Bloque 1
11 |
12 | 13 | 14 | 15 | 16 |

Bloque válido

17 |

Bloque no válido

18 | 19 |
20 |
Bloque 2
21 |
22 | 23 | 24 | 25 | 26 |

Bloque válido

27 |

Bloque no válido

28 | 29 |
30 |
Bloque 3
31 |
32 | 33 | 34 | 35 | 36 |

Bloque válido

37 |

Bloque no válido

38 | 39 |
40 |
Bloque 4
41 |
42 | 43 | 44 | 45 | 46 |

Bloque válido

47 |

Bloque no válido

48 | 49 |
50 |
Bloque 5
51 |
52 | 53 | 54 | 55 | 56 |

Bloque válido

57 |

Bloque no válido

58 | 59 |
60 |
61 | -------------------------------------------------------------------------------- /src/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, Directive, ElementRef, AfterViewInit} from '@angular/core'; 2 | import { sha256 } from 'js-sha256'; 3 | 4 | var mineWorker = ` 5 | self.onmessage = function(oEvent){ 6 | var sha256 = oEvent.data.sha; 7 | var data = oEvent.data.data; 8 | var hash = ""; 9 | var nonce = 0; 10 | while(!hash.startsWith("0000")){ 11 | nonce++; 12 | hash = sha256(nonce + ""+data); 13 | } 14 | console.log("HASH: "+hash+"\tNONCE: "+nonce); 15 | postMessage(nonce); 16 | 17 | } 18 | `; 19 | 20 | class Lesson { 21 | public show: boolean; 22 | constructor(){ 23 | this.show = false; 24 | } 25 | change(){ 26 | this.show = !this.show; 27 | } 28 | } 29 | 30 | @Component({ 31 | selector: "lesson-tokens", 32 | templateUrl: "lesson.tokens.html" 33 | }) 34 | 35 | export class LessonTokens extends Lesson{ 36 | 37 | } 38 | 39 | @Component({ 40 | selector: "lesson-thanks", 41 | templateUrl: "lesson.thanks.html" 42 | }) 43 | 44 | export class LessonThanks extends Lesson{ 45 | 46 | } 47 | 48 | @Component({ 49 | selector: "lesson-hash", 50 | templateUrl: "lesson.hash.html" 51 | }) 52 | 53 | export class LessonHash extends Lesson{ 54 | data: string; 55 | hash256: string; 56 | inputChange(){ 57 | this.hash256 = sha256(this.data); 58 | } 59 | } 60 | 61 | @Component({ 62 | selector: "lesson-block", 63 | templateUrl: "lesson.block.html" 64 | }) 65 | 66 | export class LessonBlock extends Lesson{ 67 | valid: boolean; 68 | data: string; 69 | hash256: string; 70 | nonce: string; 71 | inputChange(){ 72 | this.hash256 = sha256(this.nonce + this.data); 73 | this.valid = this.hash256.startsWith("000"); 74 | } 75 | mine(){ 76 | var hash = this.hash256; 77 | var nonce = 0; 78 | while(!hash.startsWith("000") || nonce==0){ 79 | nonce++; 80 | hash = sha256(nonce + ""+this.data); 81 | } 82 | this.hash256 = hash; 83 | this.nonce = ""+nonce; 84 | this.valid = true; 85 | } 86 | } 87 | 88 | @Component({ 89 | selector: "lesson-blockchain", 90 | templateUrl: "lesson.blockchain.html" 91 | }) 92 | export class LessonBlockchain extends Lesson{ 93 | nonce: string[]; 94 | data: string[]; 95 | valid: boolean[]; 96 | hash256: string[]; 97 | 98 | constructor(){ 99 | super(); 100 | this.nonce = new Array(5); 101 | this.data = new Array(5); 102 | this.valid = new Array(5); 103 | this.hash256 = new Array(5); 104 | } 105 | 106 | inputChange(){ 107 | for(var i=0;i<5;i++){ 108 | this.hash256[i] = sha256(this.nonce[i]+this.data[i]+this.hash256[i-1]); 109 | this.valid[i] = this.hash256[i].startsWith("000"); 110 | } 111 | } 112 | mine(id: number){ 113 | var hash = this.hash256[id]; 114 | var nonce = 0; 115 | while(!hash.startsWith("000") || nonce == 0){ 116 | nonce++; 117 | hash = sha256(nonce+this.data[id]+this.hash256[id-1]); 118 | } 119 | this.hash256[id] = hash; 120 | this.nonce[id] = ""+nonce; 121 | this.valid[id] = true; 122 | 123 | } 124 | } 125 | 126 | @Component({ 127 | selector: "lesson-distributed", 128 | templateUrl: "lesson.distributed.html" 129 | }) 130 | export class LessonDistributed extends Lesson{ 131 | nonceA: string[]; 132 | nonceB: string[]; 133 | nonceC: string[]; 134 | dataA: string[]; 135 | dataB: string[]; 136 | dataC: string[]; 137 | validA: boolean[]; 138 | validB: boolean[]; 139 | validC: boolean[]; 140 | hash256A: string[]; 141 | hash256B: string[]; 142 | hash256C: string[]; 143 | 144 | constructor(){ 145 | super(); 146 | this.nonceA = new Array(5); 147 | this.nonceB = new Array(5); 148 | this.nonceC = new Array(5); 149 | this.dataA = new Array(5); 150 | this.dataB = new Array(5); 151 | this.dataC = new Array(5); 152 | this.validA = new Array(5); 153 | this.validB = new Array(5); 154 | this.validC = new Array(5); 155 | this.hash256A = new Array(5); 156 | this.hash256B = new Array(5); 157 | this.hash256C = new Array(5); 158 | for(var i=0;i<5;i++){ 159 | this.hash256A[i] = "0"; 160 | this.hash256B[i] = "0"; 161 | this.hash256C[i] = "0"; 162 | } 163 | } 164 | 165 | inputChangeA(){ 166 | for(var i=0;i<5;i++){ 167 | this.hash256A[i] = sha256(this.nonceA[i]+this.dataA[i]+this.hash256A[i-1]); 168 | this.validA[i] = this.hash256A[i].startsWith("000"); 169 | } 170 | } 171 | inputChangeB(){ 172 | for(var i=0;i<5;i++){ 173 | this.hash256B[i] = sha256(this.nonceB[i]+this.dataB[i]+this.hash256B[i-1]); 174 | this.validB[i] = this.hash256B[i].startsWith("000"); 175 | } 176 | } 177 | inputChangeC(){ 178 | for(var i=0;i<5;i++){ 179 | this.hash256C[i] = sha256(this.nonceC[i]+this.dataC[i]+this.hash256C[i-1]); 180 | this.validC[i] = this.hash256C[i].startsWith("000"); 181 | } 182 | } 183 | mineA(id: number){ 184 | var hash = this.hash256A[id]; 185 | var nonce = 0; 186 | while(!hash.startsWith("000") || nonce == 0){ 187 | nonce++; 188 | hash = sha256(nonce+this.dataA[id]+this.hash256A[id-1]); 189 | } 190 | this.hash256A[id] = hash; 191 | this.nonceA[id] = ""+nonce; 192 | this.validA[id] = true; 193 | 194 | } 195 | mineB(id: number){ 196 | var hash = this.hash256B[id]; 197 | var nonce = 0; 198 | while(!hash.startsWith("000") || nonce == 0){ 199 | nonce++; 200 | hash = sha256(nonce+this.dataB[id]+this.hash256B[id-1]); 201 | } 202 | this.hash256B[id] = hash; 203 | this.nonceB[id] = ""+nonce; 204 | this.validB[id] = true; 205 | 206 | } 207 | mineC(id: number){ 208 | var hash = this.hash256C[id]; 209 | var nonce = 0; 210 | while(!hash.startsWith("000") || nonce == 0){ 211 | nonce++; 212 | hash = sha256(nonce+this.dataC[id]+this.hash256C[id-1]); 213 | } 214 | this.hash256C[id] = hash; 215 | this.nonceC[id] = ""+nonce; 216 | this.validC[id] = true; 217 | 218 | } 219 | } 220 | 221 | @Component({ 222 | selector: 'home', 223 | templateUrl: 'home.component.html' 224 | }) 225 | 226 | export class HomeComponent implements AfterViewInit{ 227 | ngAfterViewInit(){ 228 | try{ 229 | /*(adsbygoogle = window.adsbygoogle || []).push({}); 230 | (adsbygoogle = window.adsbygoogle || []).push({});*/ 231 | }catch(e){ 232 | 233 | } 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /src/assets/images/social_flat_rounded_rects_svg/Reddit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/home/lesson.distributed.html: -------------------------------------------------------------------------------- 1 |

Blockchain distribuida

2 |
3 |

Ya hemos visto que en una Blockchain la facilidad de modificar la información contenida en los bloques se va haciendo cada vez más difícil. No obstante, esto no es suficiente para aplicaciones más universales. En concreto, Bitcoin y Ethereum usan blockchains distribuidas.

4 |

En una blockchain distribuida no basta con que la cadena sea válida (todos sus bloques sean válidos), sino que además debe de haber un consenso

5 |

Imagina una blockchain distribuida con 3 nodos. El Nodo A decide modificar un bloque, realiza todos los minados pertinentes y su cadena ahora es válida. ¿Cómo elije el sistema que cadena es válida y cuál no? Fácil. Si una cadena modifica el contenido de un bloque, aunque realice todos sus minados los hashes resultantes van a ser distintos. Realmente, solo comprobando el hash del último bloque es posible saber si una cadena ha sufrido una modificación que el resto no tiene.

6 |

Esa cadena con un último bloque de hash distinto al resto se quedará huérfana y el resto de bloques que lleguen a la red se pondrán sobre las cadenas que tienen consenso entre sí. En redes como Bitcoin o Ethereum el consenso se logra con el 51% de los nodos.

7 |
8 |

Aquí tienes una mini-red con 3 nodos. Primero intenta que todos tengan el mismo contenido. Después intenta modificar una cadena y observa lo que ocurre.

9 |

Nodo A

10 |
Bloque 1
11 |
12 | 13 | 14 | 15 | 16 |

Bloque válido

17 |

Bloque no válido

18 | 19 |
20 |
Bloque 2
21 |
22 | 23 | 24 | 25 | 26 |

Bloque válido

27 |

Bloque no válido

28 | 29 |
30 |
Bloque 3
31 |
32 | 33 | 34 | 35 | 36 |

Bloque válido

37 |

Bloque no válido

38 | 39 |
40 |

Nodo B

41 |
Bloque 1
42 |
43 | 44 | 45 | 46 | 47 |

Bloque válido

48 |

Bloque no válido

49 | 50 |
51 |
Bloque 2
52 |
53 | 54 | 55 | 56 | 57 |

Bloque válido

58 |

Bloque no válido

59 | 60 |
61 |
Bloque 3
62 |
63 | 64 | 65 | 66 | 67 |

Bloque válido

68 |

Bloque no válido

69 | 70 |
71 |

Nodo C

72 |
Bloque 1
73 |
74 | 75 | 76 | 77 | 78 |

Bloque válido

79 |

Bloque no válido

80 | 81 |
82 |
Bloque 2
83 |
84 | 85 | 86 | 87 | 88 |

Bloque válido

89 |

Bloque no válido

90 | 91 |
92 |
Bloque 3
93 |
94 | 95 | 96 | 97 | 98 |

Bloque válido

99 |

Bloque no válido

100 | 101 |
102 |

Resultado

103 |

Las blockchains contienen exactamente el mismo contenido. Todas son válidas

104 |

El nodo A ha intentado manipular los contenidos del blockchain

105 |

El nodo B ha intentado manipular los contenidos del blockchain

106 |

El nodo C ha intentado manipular los contenidos del blockchain

107 |

No hay consenso mayoritario sobre que versión de la blockchain es la correcta

108 |
109 | --------------------------------------------------------------------------------