+ - 0:00:00
Notes for current slide
Notes for next slide

Blockchain for devs

Sesión 3: Introducción al desarrollo de Smart Contracts

Carlos Buendía (@buendiadas)

1 / 57

Agenda

  1. Introducción
  2. Clientes
  3. Consola
  4. Interactuación Externa: Web3
  5. Solidity
  6. Ejemplos Smart Contracts
  7. Ejercicio con Token
2 / 57

1: Arquitectura de una DApp

image

3 / 57

Agenda

  1. Introducción
  2. Clientes
  3. Consola
  4. Solidity
  5. Ejemplos Smart Contracts
  6. Ejercicio con Token
4 / 57

2: Clientes

Interfaz con la blockchain capaz de recuperar y verificar información de la Blockchain

Todos los clientes deberían tener las mismas funcionalidades

Diferentes implementaciones puede dar lugar a problemas

5 / 57

Geth

¿Por qué Geth?

  • Cliente más popular
  • Compatibilidad multiplaforma

3 interfaces:

  • Linea de sub-comandos
  • Un servidor en JSON-RPC
  • Una consola integrada (Web3.js)

El cliente de Ethereum es válido tanto para la red principal (Main net), como para diferentes implementaciónes (Ropsten, Private chain...)

6 / 57

Geth

Instalación

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository -y ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install ethereum

Con solo esto, ya somos capaces de interactuar con Ethereum!

7 / 57

Geth

Flags

La ejecución de Geth admite numerosos "flags", algunos de los más importantes:

Flag Descripción Por defecto
--networkid ID de la blockchain 0 (main net)
--rpc Permiso a la interfaz RPC true
--datadir Path que almacena la blockchain (Linux) .ethereum/chaindata
--rpcapi APIs abiertas vía RPC web3
--rpcport Puerto de acceso a RPC 8545
--rpccorsdomain Dominios de acceso a RPC localhost
--port Puerto de conexión para otros nodos 30303
8 / 57

Geth

Tipos de blockchain disponibles:

  • Main net: network_id=0, o sin utilizar flags
  • Testnet (Ropsten): network_id=1, o con el flag --testnet
  • Private Network: network_id=your_own_network_id Normalmente, los contratos siguen el siguiente proceso de deployment:
    • Prueba en una red simulada (que posteriormente veremos como testRPC)
    • Pruebas en una red privada o testnet
    • Deployment a Main Net. En este curso comenzaremos probando las blockchain privadas, posteriormente se probará la testnet, y finalmente se utilizará testRPC para la simulación.
9 / 57

Geth

Blockchain privada

Dos recursos necesarios para comenzarla:

  • Network id: Elegid el que deseeis
  • Archivo genesis: Parámetros que definirán finalmente la blockchain (Genesis block):
    • gasLimit: Valor que define el total de gas que puede ser gastado en un bloque
    • difficulty: Valor que define el target de dificultad (Recordar dificultad mining Bitcoin). En una privada, valor bajo (minado rápido)
    • alloc: Define wallets con prelocalización de Ether Información de los parámetros encontrados en el genesis block pueden ser encontrados en el yellow paper
10 / 57

Geth

Ejemplo archivo génesis:

{
"nonce": "0x0000000000000042",
"timestamp": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x0",
"gasLimit": "0x8000000",
"difficulty": "0x400",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x3333333333333333333333333333333333333333",
"alloc": {
}
}
11 / 57

Geth

Inicialización de una blockchain privada

  • 1: Inicialización del bloque génesis:
    geth --datadir </path/a/bloques/> init genesis.json
  • 2: Ejecución de la blockchain:
    $ geth + Flags...
12 / 57

TestRPC

  • Incluso las blockchain privadas son demasiado lentas/ineficientes a la hora de desarrollar
  • testRPC es una Librería en JS que simula un nodo completo de una blockchain privada, o una blockchain real a partir de determinado punto
  • Para el desarrollo de aplicaciones del curso, se utilizará esta librería.

    Ejecutar

    $ testrpc
13 / 57

TestRPC

Options (From the Docs):

  • -a or --accounts: Specify the number of accounts to generate at startup.
  • -b or --blocktime: Specify blocktime in seconds for automatic mining. Default is 0 and no auto-mining.
  • -d or --deterministic: Generate deterministic addresses based on a pre-defined mnemonic.
  • -m or --mnemonic: Use a specific HD wallet mnemonic to generate initial addresses.
  • -p or --port: Port number to listen on. Defaults to 8545.
  • -h or --hostname: Hostname to listen on. Defaults to Node's server.listen() default.
  • -s or --seed: Use arbitrary data to generate the HD wallet mnemonic to be used.
  • -g or --gasPrice: Use a custom Gas Price (defaults to 20000000000)
  • -l or --gasLimit: Use a custom Gas Limit (defaults to 0x47E7C4)
  • -f or --fork: Fork from another currently running Ethereum client at a given block. Input should be the HTTP location and port of the other client, e.g. http://localhost:8545. You can optionally specify the block to fork from using an @ sign: http://localhost:8545@1599200.
14 / 57

Ejercicio 1

Despliegue de una blockchain privada.

Crear una blockchain privada con los siguientes parámetros.

Flag Valor
--networkid 25052017
--rpc true
--datadir $HOME/documents/blockchain/private_blockchain
--rpcapi web3
--rpcport 8546
--rpccorsdomain localhost
--port 30303
15 / 57

Ejercicio 1

Conectando al cliente

Una vez inicializado y corriendo la blockchain, encontraréis un archivo .ipc. Conectar a la blockchain a través de IPC:

geth attach ipc: /your/path/to/your/ipc

¡Ya estamos conectados a nuestro cliente y podemos comunicarnos via Web3!

16 / 57

Agenda

  1. Introducción
  2. Clientes
  3. Consola
  4. Solidity
  5. Ejemplos Smart Contracts
  6. Ejercicio con Token
17 / 57

Consola

A través de la consola podemos acceder a diferentes funciones de Web3 y gestión de claves: Probar interfaces utilizando como ejemplos:

> admin // Gestión de la red
> eth // web3.eth
> personal //Gestión de claves personal
> miner //Gestión de minería
18 / 57

Consola

Creación de una cuenta

  • 1: A través de la interfaz eth, podemos ver las cuentas disponibles utilizando:
    > eth.accounts // Array
    > eth.accounts[0] //Primera cuenta
  • 2: Podemos crear una cuenta desde la consola, utilizando 'personal'
    > personal.newAccount()
  • 3: Como respuesta, nos pedirán una contraseña, que cifrará la clave privada almacenada
    Passphrase:
    Repeat passphrase:
19 / 57

Consola

Creación de una cuenta

  • 4: Una vez obtenida la cuenta, podemos observar la aparición de una nueva cuenta utilizando eth.accounts
  • 5: La nueva cuenta estará almacenada (cifrada con la passphrase) en el directorio datadir/keystore
20 / 57

Consola

Importación de una cuenta

De la misma manera que hemos creado una cuenta, podemos importarlas de carteras externas. Para ello, únicamente necesitamos realizar:

geth account import <keyfile>

Exportación de una cuenta

Para exportar una cuenta y tratarla desde una wallet diferente, únicamente necesitamos utilizar el archivo alojado en keystore.

21 / 57

Ejercicio 2:

Importación de una Cuenta

MyEtherWallet es un ejemplo muy generalizado de empleo de Wallets. Alguna vez pueden haberte recomendado utilizarla para acceder a un token sale, pero: ¿Cómo importar la wallet desde aquí?

Acceder a MyEtherWallet y conseguir importar una cuenta en vuestra wallet de Geth.

¿Cuál es tu clave privada?

22 / 57

Ejercicio 3:

Exportación de una Cuenta

De la misma manera que hemos importado una cuenta podemos exportarla a MyEtherWallet, utilizando el archivo de keystore.

Exportar una Wallet de MyEtherWallet e importarla para acceder a ella desde la consola de geth.

23 / 57

Consola

Minería

  • Ethereum (hasta el momento, Mayo 2017) utiliza como algoritmo de consenso Proof of Work
  • Dificultad ajustada dinámicamente, bloques producidos cada 12 segundos de media (realmente 14)
  • Algoritmo de Ethereum (EthHash) incluye un recurso que hace recalcular el algoritmo cada cierto tiempo, llamado DAG
  • El DAG tiene un tamaño de al rededor de 1 GB, y tarda cierto tiempo en generarse
24 / 57

Consola

Minería

  • Podemos acceder al minero y sus funciones en la consola utilizando el comando 'miner'. Principalmente se utilizarán dos funciones
    • 1: Start
      > miner.start()
    • 2: Stop
      > miner.stop()
      Ejecutar el comando de 'start', ¿Qué ocurre?
25 / 57

Consola

Minería

Al ejecutar miner.start, obtendremos un resultado como el siguiente:

I0526 02:22:54.754878 miner/worker.go:514] commit new work on block 4884 with 0 txs & 0 uncles. Took 290.93µs
I0526 02:22:59.329896 miner/unconfirmed.go:105] 🔗 ** mined block #4879** [6e362780…] reached canonical chain
I0526 02:22:59.329921 miner/unconfirmed.go:83] 🔨 mined potential block #4884 [afb8d8da…], waiting for 5 blocks to confirm
I0526 02:22:59.330157 miner/worker.go:514] commit new work on block 4885 with 0 txs & 0 uncles. Took 198.083µs

Ejecutar:

> eth.getBalances(eth.accounts[0])

¿Qué ocurre?

26 / 57

Consola

Minería

  • Para recibir las recompensas, necesitamos fijar la cuenta sobre la que se recibirán los beneficios.
  • Realizamos esto a través del comando:
    > miner.setEtherBase(eth.accounts[0])
    Podemos volver a minar, obteniendo ahora los beneficios asociados:
    > miner.setEtherBase(eth.accounts[0])
27 / 57

Consola

Transacciones

Recordando la estructura de las transacciones repasada en la clase anterior:

  • Recipiente
  • Firma
  • Cantidad de Ether a enviar
  • Campo datos(opcional)

Al realizar una transacción, desde consola, debemos especificar

  • Emisor-from (cuenta que vamos a utilizar para la transacción)
  • Receptor-to (cuenta que va a recibir el ETH)
  • Valor-value (cantidad que vamos e enviar, en wei)
28 / 57

Consola

Transacciones

Todo esto, utilizando la consola con javascript, se realizaría de la siguiente manera:

var sender = eth.accounts[0];
var receiver = eth.accounts[1];
var amount = web3.toWei(0.01, "ether")
eth.sendTransaction({from: sender, to: receiver, value: web3.toWei(1, "ether")})

Observar la primera consola, qué ocurre?

29 / 57

Consola

Transacciones

A partir de aquí, podemos acceder a otras herramientas para hacer seguimiento de las transacciones en la blockchain.

  • Ver el status del transaction pool
    > txpool.status
  • Ver el número de transacciones pendientes en el bloque
    > eth.getBlockTransactionCount("pending");
  • Ver el número de transacciones pendientes en el bloque
    > eth.getBlockTransactionCount("pending");
  • Ver todas las transacciones pendientes del bloque eth.getBlock("pending", true).transactions

    Al realizar una transacción, desde consola, debemos especificar

    • Emisor-from (cuenta que vamos a utilizar para la transacción)
    • Receptor-to (cuenta que va a recibir el ETH)
    • Valor-value (cantidad que vamos e enviar, en wei)
30 / 57

Consola

Contratos

  • En la blockchain de Ethereum los contratos residen en formato binario (bytecode)
  • Para escribirlos, se utilizan normalmente lenguajes de más alto nivel:
    • Solidity
    • Serpent
    • LLL
  • Esto necesita de un compilador. Nosotros usaremos solidity:

  • La compilación/deployment/ejecución también puede realizarse a través de consola

  • Sin embargo esto resulta mucho más sencillo comenzando a utilizar librerías externas: Web3

  • Para ello, en lugar de utilizar el cliente geth comenzaremos a utilizar la librería testRPC

    Web3

    • Principal interfaz para interactuación con la blockchain

    • Ofrece, a través de javascript una librería de herramientas completa para interactuar y desarrollar con la blockchain.

    • Interactuación con otros servicios adicionales de Ethereum (keystore, whisper, swarm)

    Ejemplos:

    • Herramienta externa: Encriptación (web3.sha3())
    • Utilización de la blockchain: web3.eth.sendTransaction(object)
    • Utilización de servicios extra Ethereum: shh
31 / 57

Web3

  • Instalación:

    npm install web3

  • Abre Geth

  • Ejecuta el siguiente código: node web3-test.js

    var Web3 = require('web3');
    var web3 = new Web3(
    new Web3.providers.HttpProvider("http://localhost:8545"));
    web3.eth.getBlock(0, function(error, result){
    if(!error)
    console.log(result)
    else
    console.error(error);
    });
32 / 57

Web3

Realización de una transacción

var Web3 = require('web3');
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));
web3.eth.sendTransaction(tx_object)
console.log("Balance 0" + web3.eth.getBalance(web3.eth.accounts[0]))
console.log( "Balance 1" + web3.eth.getBalance(web3.eth.accounts[1])
web3.eth.sendTransaction ({from:web3.eth.accounts[0],
to: web3.eth.accounts[1],
value: web3.toWei(1, "ether")})
console.log("Balance 0" + web3.eth.getBalance(web3.eth.accounts[0]))
console.log("Balance 1" + web3.eth.getBalance(web3.eth.accounts[1])
33 / 57

Web3

Ejercicio

A través de el ejemplo anterior y los ejemplos de transacciones anteriores, crea el fichero tx_sender.js

34 / 57

Web3

Web3 no solo provee de herramientas propias de la blockchain de ethereum sino de cualquier facilitador útil para el desarrollo en Ethereum. Un ejemplo es la utilización de Hashes:

Encriptando con KECCAK-256

  • En un nuevo archivo ejecuta
    $ node
    (Initialize web3)
    web3.sha3("Hello Ethereum Course")
35 / 57

Web3

Compilando un contrato

Crea el siguiente archivo (compilecontract.js):

var Web3 = require('web3');
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));
var source = 'pragma solidity ^0.4.6; contract demo {string public name = "buendiadas"; function changeName(string _newName){name = _newName; } }';
var compiled = web3.eth.compile.solidity(source);
console.log(compiled);
console.log("ABI")
console.log( compiled.info.abiDefinition);

Ejecuta:

$ node compilecontract.js
36 / 57

Web3

Subiendo el contrato

Copia las anteriores lineas en un nuevo fichero(e.g. contractupload.js), y añade las siguientes:

var nameContract= web3.eth.contract(compiled.info.abiDefinition);
var uploadedContract = nameContract.new({from:web3.eth.accounts[0], data: compiled.code, gas: 1000000}, function(e, contract){
if(!e) {
if(!contract.address) {
console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");
} else {
console.log("Contract mined! Address: " + contract.address);
console.log(contract);
}
}
});

En terminal:

$ node contractupload.js
37 / 57

Web3

Llamando a un contrato

Recupera los valores ABI, y contract Address del valor anterior

Con estos, sustituye en el siguiente script, y crea un nuevo fichero (getname.js)

var Web3 = require('web3');
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));
var ABI = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_newName","typ$
var contractAddress = "0xbbfd34ccf4bd62ec0d33d8b25c687c34888941af";
var contract = web3.eth.contract(ABI).at(contractAddress);
contract.name.call(function(data){
console.log(data)
});
38 / 57

Web3

Conectando con solidity

Recupera los valores ABI, y contract Address del valor anterior

Accede a el IDE oficial (REMIX) : http://ethereum.github.io/browser-solidity/#version=soljson-v0.4.9+commit.364da425.js

39 / 57

Consola

Contratos

  • En la blockchain de Ethereum los contratos residen en formato binario (bytecode)
  • Para escribirlos, se utilizan normalmente lenguajes de más alto nivel:
    • Solidity
    • Serpent
    • LLL
  • Esto necesita de un compilador. En el caso de Ethereum, el compilador viene por defecto en la instalación.
40 / 57

Web3

  • Principal interfaz para interactuación con la blockchain

  • Ofrece, a través de javascript una librería de herramientas completa para interactuar y desarrollar con la blockchain.

  • Interactuación con otros servicios adicionales de Ethereum (keystore, whisper, swarm)

Ejemplos:

  • Herramienta externa: Encriptación (web3.sha3())
  • Utilización de la blockchain: web3.eth.sendTransaction(object)
  • Utilización de servicios extra Ethereum: shh
41 / 57

Web3

  • Instalación:

    npm install web3

  • Abre Geth

    $ geth --networkid 03032017 --rpccorsdomain "*" --datadir "/home/satoshi/chain" --port "30303" "db,eth,net,web3"

  • Ejecuta el siguiente código: node web3-test.js

    var Web3 = require('web3');
    var web3 = new Web3(
    new Web3.providers.HttpProvider("http://localhost:8545"));
    web3.eth.getBlock(0, function(error, result){
    if(!error)
    console.log(result)
    else
    console.error(error);
    });
42 / 57

Web3

Realización de una transacción

Recordamos el objeto transaction:

from, to, value, data, *nonce

Transacción entre cuentas externas --> Campo value > 0, no data

> web3.eth.sendTransaction(tx_object)
> web3.eth.sendTransaction ({from:web3.eth.accounts[0],
to: web3.eth.accounts[1],
value: web3.toWei(1, "ether")})
> web3.eth.getBalance(web3.eth.accounts[0])
> web3.eth.getBalance(web3.eth.accounts[1])
43 / 57

Solidity

Estructura de un contrato

  • Similar a clases en OOP

    contract mortal is owned {
    }
  • Referencia a Internal Storage (Variables de estado) (Recordar account object)

    • Nonce
    • Ether balance
    • Contract code
    • The account's storage
  • Computación descentralizada (functions)
44 / 57

Solidity

Estructura de un contrato

  • 1: Versión pragma

    0.x.0
    `

    or

    x.0.0

    pragma solidity ^0.4.0;

    -2: Importando otros contratos:

    import "filename";

45 / 57

Solidity

Tipos

Solidity permite los siguientes tipos por defecto:

  • bool: Variable booleana, true/failsafe
  • uintxxx: Enteros, xxx representa el número de bits con el que se representa
  • address: Direcciones de Ethereum (EOA, or SC). Cada address tiene asociadas:
    • balance
    • transfer
  • bytes: An empty array of bites
  • string: An string
46 / 57

Solidity

Variables de estado

Almacenadas en el storage asociado a cada account

contract demo {
string public name = "buendiadas";
....
47 / 57

Solidity

Funciones

Computación descentralizada en función de los inputs de la transacción.

function changeName(string _newName){
name = _newName; }
}
48 / 57

Solidity

Modificadores

Ejecución de condiciones previas a la ejecución de dicho contrato. Suelen utilizarse para generar restricciones

pragma solidity ^0.4.0;
contract owned {
function owned() { owner = msg.sender; }
address owner;
modifier onlyOwner {
if (msg.sender != owner)
throw;
_;
}
}
contract mortal is owned {
}
}
49 / 57

Solidity

Funciones

Computación descentralizada en función de los inputs de la transacción.

function changeName(string _newName){
name = _newName; }
}
50 / 57

Eventos

Log de Ethereum (Recordar blockchain structure). Permiten subir información externa a la blockchain, donde se almacena únicamente el hash.

event NameChanged(string _oldName, string _newName);
function changeName(string _newName){
name = _newName;
NameChanged(name, _newName);
}
}
51 / 57

Ejemplo: Metacoin

contract MetaCoin {
mapping (address => uint) balances;
function MetaCoin() {
balances[tx.origin] = 10000;
}
function sendCoin(address receiver, uint amount) returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[receiver] += amount;
return true;
}
function getBalance(address addr) returns(uint) {
return balances[addr];
}
}
52 / 57

Ejercicio 4

Registro de nombres

A partir de los ejemplos mostrados en la definición de los diferentes componentes, escribir un SC (ENS) que :

  • Tenga un registro de nombres web
  • El registro de nombre solo puede ser editado por la persona a la que está asociado
  • Cualquier persona puede acceder al nombre de una persona
  • Al cambiar de nombre, se lance un evento.
  • ++PRO: El linkeo del nombre no se hace mediante el nombre en si, sino mediante su Hash
53 / 57

Ejercicio 5

Creación moneda

A partir de el contrato anterior, crear un token que tenga las siguientes reglas económicas:

  • Existe una dirección central, que carga una fee por cada transacción que se realiza.
  • Esta fee puede ser cargada de dos formas:
    • Fácil: Enviando por cada transacción un porcentaje de los tokens
    • Medio: Modificando el total de circulación de moneda (diluyendo a los holders)
  • Adicional: La dirección seleccionada puede decidir bloquear la posibilidad de transacciones.
  • ++ : Probar a utilizar la restricción a través de un modifier.
  • +++: Modificar las condiciones para que la lógica del dueño provenga de un contrato "owner"
54 / 57

ERC20 Token Standard

  • Debido a la aparición de diferentes tokens con diferentes tipos de implementaciones, la integración en estructuras más complejas era complicada
  • La creación de un Standard en la creación de Tokens permitió la integración en plataformas como
  • También se eliminan problemas de seguridad asociados a la creación de cada token
  • En la actualidad, prácticamente todos los tokens sobre Ethereum se hacen sobre esta interfaz.

La especificación del estandard puede encontrarse en el siguiente link

55 / 57

Ejemplo: ICO MatchPool

https://github.com/Matchpool/contracts

  • ¿Cómo asocia los Tokens?

  • ¿Quién se queda el Ether que se recibe?

  • ¿Qué periodos hay de precios?

  • ¿Cuántos tokens hay en total?

  • ¿Cuánto tiempo dura la ICO?

  • ¿Cuánto dinero almacena el contrato?

56 / 57
57 / 57

Agenda

  1. Introducción
  2. Clientes
  3. Consola
  4. Interactuación Externa: Web3
  5. Solidity
  6. Ejemplos Smart Contracts
  7. Ejercicio con Token
2 / 57
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow