En esta primera versión sólo se explica como configurar y desplegar una testnet en OS X. Aun así, hay que tener en cuenta que lo único que varía son los pasos de instalación de los distintos clientes.
$ brew update
$ brew upgrade
$ brew tap ethereum/ethereum
$ brew install ethereumPara comprobar que funciona:
$ geth consoleUna vez sabemos que el cliente de GoEthereum (geth) funciona se deben crear dos cuentas:
$ geth account newLa ejecución de este comando espera recibir una contraseña que será la que desbloquee la cuenta.
Para configurar una red de Ethereum se debe crear un fichero conocido como "Bloque Génesis" en el que se especifican varios parámetros:
{
"config": {
"chainId": 2000,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0
},
"difficulty": "400",
"gasLimit": "2000000",
"alloc": {
"b38935ab356f828df2ee27ef525d9649b9b9e18f": {
"balance": "100000000000000000000000"
},
"9b0b0e4ba1e990704f46840fd42bfb3352424e49": {
"balance": "120000000000000000000000"
}
}
}Identifica la cadena y se usa para evitar ataques de reinyección.
Relacionados con veriones y posibles forks que pueda haber en la cadena.
Hace referencia a la dificultad de minado. En este caso le damos una valor bajo (400) para que no tarden demasiado en generarse los bloques.
Especifica el máximo gas que se puede gastar en cada transacción.
Aquí se especifican los addresses de las cuentas generadas previamente y el balance que se le asigna a cada una (100.00 Eth y 120.00 Eth respectivamente). Para obtener esto addresses basta con ejecutar:
$ geth account list$ geth --datadir ./myDataDir init ./myGenesis.jsoncp -R /<Directorio de la cuenta>/keystore/<cuenta1>. ./myDataDir/keystore/.$ geth --datadir ./myDataDir --networkid 1234 console 2>> myEth.logDesde otro consola se pueden seguir los logs que se generen mediante:
tail -f myEth.logSi no se conoce el directorio en el que está almacenada la información asociada a una cuenta basta con listarla:
$ geth account listPara comprobar que se ha hecho correctamente basta con ejecutar desde la console de geth:
> eth.accountsó
> personal.listAccountsDesde la consola de geth:
> miner.setEtherbase(web3.eth.accounts[0])
> miner.start()Para comprobar que ha funcionado basta con comprobar el balance de la cuenta:
> eth.getBalance(eth.coinbase)Si la cuenta que ha comenzado a minar era la que tenía 100.00 Eth, debería tener un saldo algo mayor que 1e+23, y si era la que tenía 120.00 Eth, el saldo debería ser algo superior a 1.2e+23. Aun así, hasta que el minero comienza a minar pueden pasar entre 2 y 3 minutos, por tanto si no observas cambios espera 😉
Si quisieses que dejase de minar bastaría con ejecutar desde la consola de geth:
> miner.stop()El proceso es muy similar al anterior, pero se debe unir al peer actual. Primero se debe iniciar la red con el mismo fichero de configuración que para el nodo anterior.
$ geth --datadir ./peer2DataDir init ./myGenesis.jsonDesde otro terminal debemos copiar las claves asociadas a la segunda cuenta:
$ cp -R /<Directorio de la cuenta>/keystore/<cuenta2>/. ./peer2DataDir/keystore/.Por último para levantar el nodo se debe indicar un puerto distinto al del primer peer para evitar que ambos utilicen el mismo.
$ geth --datadir ./peer2DataDir --networkid 1234 --port 30304 console 2>> myEth2.logPara unir ambos peers primero debemos obtener la dirección del enode de la primera cuenta. Para ello, desde la primera consola de geth:
> admin.nodeInfo.enodeCon esta información desde la segunda consola de geth, la asociada al peer2, se debe ejecutar:
> admin.addPeer("<Valor copiado>")Comprobación (desde cualquiera de los peers):
> admin.peersEn esta sección se explica como desplegar e instanciar desde geth un SmartContract.
$ npm install -g solc$ solcjs --abi Election.sol
$ solcjs --bin Election.sol$ more Election_sol_Election.abi
$ more Election_sol_Election.binPrimero se debe desbolquear la cuenta desde la que se va a desplegar el SmartContract
> personal.unlockAccount(eth.accounts[0])Una vez está desbloqueada la cuenta se debe introducir el abi y el binario para poder generar una instancia del SmartContract.
> var election = eth.contract(<Contenido del ABI>)
> var bytecode = '0x<Contenido del binario>'
> var deploy = {from: eth.accounts[0], data: bytecode, gas: 2000000}
> var electionPartialInstance = election.new("<Parámetros de la función constructora del contrato>", deploy)
> var electionInstance = election.at(electionPartialInstance.address)Si se utiliza el contrato proporcionado para probarlo no se deben pasar parámetros a la función constructora ya que no hay, quedando por tanto la definición de la variable electionPartialInstance como sigue:
> var electionPartialInstance = election.new(deploy)Además, si al ejecutar alguna de las funciones diese un error del tipo "invalid address", para solucionarlo basta con configurar la cuenta por defecto:
> eth.defaultAccount = eth.accounts[0]Otra opción para resolver este problema sería pasar el address desde el que se desea realizar la llamada a la función como parámetro:
> election.vote(1, {from: eth.accounts[0]})Election.sol es un SmartContract muy básico que permite gestionar un sistema de votación. En el constructor del SmartContract se especifican los candidatos a los que se puede votar. Además tiene dos funciones, una que permite votar a un candidato (una cuenta sólo puede votar una vez) y un getter por candidato que permite conocer el id, el nombre y el número de votos que ha recibido.
Estas funciones se pueden llamar desde la consola de geth como sigue:
> electionInstance.vote(_candidateId)
> electionInstance.getVotes(_candidateId)La primera función imprimirá por pantalla el hash de la transacción puesto que se trata de una operación de escritura.
La segunda función imprimirá por pantalla el resultado de la consulta, es decir, el identificador del candidato, el nombre del candidato y el número de votos que ha recibido.
Además, dado que la variable candidates es pública, se puede acceder a los atributos de un candidato sin la necesidad de la función getVotes como sigue:
> electionInstance.candidates(_candidateId)Para obtener el address del SmartContract, desde el cliente geth del peer que lo ha desplegado hay que ejecutar:
> electionInstance.addressPara generar la nueva instancia desde el otro peer:
> var election = eth.contract(<Contenido del ABI>)
> var electionInstance = election.at("<Address del SmartContract>")