Mastering Bitcoin

Mastering Bitcoin


5. El Cliente Bitcoin » Utilizando la API JSON-RPC de Bitcoin Core desde la Línea de Comandos » Creando, Firmando y Enviando Transacciones Basadas en Salidas Sin Gastar

Página 25 de 98

Utilizando la API JSON-RPC de Bitcoin Core desde la Línea de Comandos

El cliente Bitcoin Core implementa una interfaz JSON-RPC que puede ser accedida también usando la herramienta de línea de comando bitcoin-cli. La línea de comandos nos permite experimentar interactivamente con las capacidades disponibles también escribiendo código de programación a través de la API. Para comenzar invoque el comando help para ver la lista de comandos disponibles del RPC de bitcoin.

$ bitcoin-cli help

addmultisigaddress nrequired ["clave",…] ( "cuenta" ) addnode "nodo" "add|remove|onetry"

backupwallet "destino"

createmultisig nrequired ["clave", …]

createrawtransaction [{"txid":"id","vout":n},…] {"dirección":monto,…}

decoderawtransaction "cadenahex"

decodescript "hex"

dumpprivkey "direcciónbitcoin"

dumpwallet "nombredearchivo"

getaccount "direcciónbitcoin"

getaccountaddress "cuenta"

getaddednodeinfo dns ( "nodo" )

getaddressesbyaccount "cuenta"

getbalance ( "cuenta" minconf )

getbestblockhash

getblock "hash" ( verbose )

getblockchaininfo

getblockcount

getblockhash index

getblocktemplate ( "objetodepeticiónjson" )

getconnectioncount

getdifficulty

getgenerate

gethashespersec

getinfo

getmininginfo

getnettotals

getnetworkhashps ( altura de bloques )

getnetworkinfo

getnewaddress ( "cuenta" )

getpeerinfo

getrawchangeaddress

getrawmempool ( verbose )

getrawtransaction "txid" ( verbose )

getreceivedbyaccount "cuenta" ( minconf )

getreceivedbyaddress "direcciónbitcoi" ( minconf )

gettransaction "txid"

gettxout "txid" n ( includemempool )

gettxoutsetinfo

getunconfirmedbalance

getwalletinfo

getwork ( "datos" )

help ( "comando" )

importprivkey "claveprivadabitcoin" ( "etiqueta" rescan ) importwallet "nombredearchivo"

keypoolrefill ( tamañonuevo )

listaccounts ( minconf )

listaddressgroupings

listlockunspent

listreceivedbyaccount ( minconf includeempty )

listreceivedbyaddress ( minconf includeempty )

listsinceblock ( "hashdebloque" target-confirmations )

listtransactions ( "cuenta" conteo desde )

listunspent ( minconf maxconf ["dirección",…] )

lockunspent unlock [{"txid":"txid","vout":n},…]

move "desdecuenta" "haciacuenta" amount ( minconf "comentario" ) ping

sendfrom "desdecuenta" "haciadirecciónbitcoin" monto ( minconf "comentario" "comentario-a" )

sendmany "desdecuenta" {"dirección":monto,…} ( minconf "comentario" ) sendrawtransaction "cadenahex" ( allowhighfees )

sendtoaddress "dirección bitcoin" cantidad ( "comentario" "comentario-para" ) setaccount "direcciónbitcoin" "cuenta"

setgenerate generate ( genproclimit )

settxfee amount

signmessage "direcciónbitcoin" "mensaje"

signrawtransaction "cadenahexadecimal" (

[{"txid":"id","vout":n,"scriptPubKey":"hex","redeemScript":"hex"},…]

["claveprivada1",…] tipodehashdefirma )

stop

submitblock "datoshexadecimales" ( "objetodeparámetrosjson" ) validateaddress "direcciónbitcoin"

verifychain ( niveldechequeo númerodebloques )

verifymessage "direcciónbitcoin" "firma" "mensaje"

walletlock

walletpassphrase "frasesecreta" timeout

walletpassphrasechange "oldpassphrase" "newpassphrase"

Obteniendo Información del Estado del Cliente Bitcoin Core

Comandos: getinfo

El comando RPC de bitcoin getinfo muestra información básica sobre el estado del nodo de la red bitcoin, la cartera, y la base de datos de la cadena de bloques. Use \1 para ejecutarlo:

$ bitcoin-cli getinfo

{

"version" : 90000,

"protocolversion" : 70002,

"walletversion" : 60000,

"balance" : 0.00000000,

"blocks" : 286216,

"timeoffset" : -72,

"connections" : 4,

"proxy" : "",

"difficulty" : 2621404453.06461525,

"testnet" : false,

"keypoololdest" : 1374553827,

"keypoolsize" : 101,

"paytxfee" : 0.00000000,

"errors" : ""

}

Los datos se devuelven en JavaScript Object Notation (JSON), un formato que puede ser fácilmente «consumido» por todos los lenguajes de programación, es también bastante legible por humanos. Entre estos datos vemos el número de versión del cliente bitcoin (90000), protocolo (70002) y monedero (60000). Vemos el balance actual contenido en el monedero, que es cero. Vemos la altura del bloque actual, mostrándonos cuántos bloques son conocidos por el cliente (286216). Vemos también varias estadísticas sobre la red bitcoin y las configuraciones relacionadas con el cliente. Exploraremos estas configuraciones en más detalle en el resto del capítulo.

Llevará bastante tiempo, seguramente más de un día, al cliente bitcoind llegar a la altura actual de la cadena de bloques cuando descargue bloques de otros clientes bitcoin. Puede ver el progreso utilizando getinfo para ver el número de bloques conocidos.

Encriptación y Configuración de la Cartera

Comandos: encryptwallet, walletpassphrase

Antes de proceder a crear claves y otros comandos, debe encriptar la cartera con una contraseña. Para este ejemplo, se usará el comando encryptwallet con la contraseña «foo». Por supuesto, ¡cambie «foo» por otra contraseña más fuerte y compleja!

$ bitcoin-cli encryptwallet foo

wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.

$

Puede verificar que la cartera ha sido encriptada ejecutando getinfo de nuevo. Esta vez verá una nueva entrada llamada unlocked_until. Es un contador que muestra cuánto tiempo estará en la memoria la contraseña de desencriptado, manteniendo la cartera desbloqueada. Al principio este tiempo será de cero, lo que significa que el monedero está bloqueado.

$ bitcoin-cli getinfo

{

"version" : 90000,

#[… other information…]

"unlocked_until" : 0,

"errors" : ""

}

$

Para desbloquear el monedero, lance el comando walletpassphrase, que tiene dos parámetros. La contraseña y un número de segundos hasta que el monedero vuelva a ser bloqueado automáticamente (una cuenta atrás):

$ bitcoin-cli walletpassphrase foo 360

$

Puede confirmar que el monedero está desbloqueado y ver el tiempo que queda ejecutando getinfo de nuevo.

$ bitcoin-cli getinfo

{

"version" : 90000,

#[… other information …]

"unlocked_until" : 1392580909,

"errors" : ""

}

Copia de Seguridad del Monedero, Volcado de Texto Plano y Restauración.

Comandos: backupwallet, importwallet, dumpwallet

A continuación, practicaremos creando un archivo de copia de seguridad y restauraremos la cartera desde la copia de seguridad. Utilice el comando backupwallet para hacer la copia, proporcionando el nombre de archivo como parámetro. Aquí hacemos la copia de seguridad al archivo wallet.backup:

$ bitcoin-cli backupwallet wallet.backup

$

Ahora, para restaurar la copia de seguridad, usamos el comando importwallet. Si su cartera está bloqueada, necesitará desbloquearla primero (ver walletpassphrase en la anterior sección) para importar la copia de seguridad:

$ bitcoin-cli importwallet wallet.backup

$

El comando dumpwallet puede ser usado para volcar el archivo en un archivo de texto legible por humanos:

$ bitcoin-cli dumpwallet wallet.txt

$ more wallet.txt

# Wallet dump created by Bitcoin v0.9.0rc1-beta (2014-01-31 09:30:15 +0100)

# * Created on 2014-02- 8dT20:34:55Z

# * Best block at time of backup was 286234

(0000000000000000f74f0bc9d3c186267bc45c7b91c49a0386538ac24c0d3a44),

# mined on 2014-02- 8dT20:24:01Z

KzTg2wn6Z8s7ai5NA9MVX4vstHRsqP26QKJCzLg4JvFrp6mMaGB9 2013-07- 4dT04:30:27Z change=1 #

addr=16pJ6XkwSQv5ma5FSXMRPaXEYrENCEg47F

Kz3dVz7R6mUpXzdZy4gJEVZxXJwA15f198eVui4CUivXotzLBDKY 2013-07- 4dT04:30:27Z change=1 #

addr=17oJds8kaN8LP8kuAkWTco6ZM7BGXFC3gk

[… many more keys …]

$

Direcciones de Cartera y Recepción de Transacciones

Comandos: getnewaddress, getreceivedbyaddress, listtransactions, getaddressesbyaccount, getbalance

El cliente bitcoin de referencia mantiene una agrupación de direcciones, el tamaño del cual se muestra en keypoolsize cuando usa el comando getinfo. Estas direcciones se generan automáticamente y pueden luego usarse como direcciones públicas de recepción o direcciones de cambio. Para conseguir una de estas direcciones, use el comando getnewaddress:

$ bitcoin-cli getnewaddress

1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL

Ahora podemos usar esta dirección para enviar una pequeña cantidad de bitcoin a nuestra cartera bitcoind desde una cartera externa (asumiendo que usted tiene algunos bitcoins guardados en una casa de cambio, cartera web u otra cartera bitcoind en otro ordenador). Para este ejemplo, enviaremos 50 milibitcoins (0,050 bitcoins) a la dirección anterior.

Ahora consultaremos al cliente bitcoind por la cantidad recibida por esta dirección, y especificaremos cuántas confirmaciones se requieren antes de que la cantidad se sume al saldo. Para este ejemplo, especificaremos cero confirmaciones. Unos segundos más tarde de enviar los bitcoins desde la otra cartera, lo veremos reflejado en la cartera. Usaremos getreceivedbyaddress con la dirección y el número de confirmaciones configurado a cero (0):

$ bitcoin-cli getreceivedbyaddress 1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL 0

0.05000000

Si omitimos el cero del final de este comando, veremos solo las cantidades que tienen al menos minconf confirmaciones, donde minconf es la configuración para el mínimo número de confirmaciones antes de que una transacción sea listada en el saldo. La configuración minconf se especifica en el archivo de configuración de bitcoind. Debido a que esta transacción fue enviada en los últimos segundos, aún no tiene confirmaciones y por tanto veremos listado un saldo de cero.

$ bitcoin-cli getreceivedbyaddress 1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL

0.00000000

Las transacciones recibidas por el monedero completo pueden verse usando el comando listtransactions:

$ bitcoin-cli listtransactions

[

{

"account" : "",

"address" : "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",

"category" : "receive",

"amount" : 0.05000000,

"confirmations" : 0,

"txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",

"time" : 1392660908,

"timereceived" : 1392660908

}

]

Podemos listar todas las direcciones del monedero usando el comando getaddressesbyaccount:

$ bitcoin-cli getaddressesbyaccount ""

[

"1LQoTPYy1TyERbNV4zZbhEmgyfAipC6eqL",

"17vrg8uwMQUibkvS2ECRX4zpcVJ78iFaZS",

"1FvRHWhHBBZA8cGRRsGiAeqEzUmjJkJQWR",

"1NVJK3JsL41BF1KyxrUyJW5XHjunjfp2jz",

"14MZqqzCxjc99M5ipsQSRfieT7qPZcM7Df",

"1BhrGvtKFjTAhGdPGbrEwP3xvFjkJBuFCa",

"15nem8CX91XtQE8B1Hdv97jE8X44H3DQMT",

"1Q3q6taTsUiv3mMemEuQQJ9sGLEGaSjo81",

"1HoSiTg8sb16oE6SrmazQEwcGEv8obv9ns",

"13fE8BGhBvnoy68yZKuWJ2hheYKovSDjqM",

"1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",

"1KHUmVfCJteJ21LmRXHSpPoe23rXKifAb2",

"1LqJZz1D9yHxG4cLkdujnqG5jNNGmPeAMD"

]

Finalmente, el comando getbalance mostrará el saldo total del monedero, añadiendo todas las transacciones confirmadas con al menos las confirmaciones de minconf:

$ bitcoin-cli getbalance

0.05000000

Si la transacción aún no se ha confirmado, el saldo devuelto por getbalance será cero. La opción de configuración minconf determina el número mínimo de confirmaciones que es necesario para que una transacción aparezca en el saldo.

Explorando y Decodificando Transacciones

Comandos: gettransaction, getrawtransaction, decoderawtransaction

Ahora exploraremos la transacción entrante que fue listada previamente usando el comando gettransaction. Podemos obtener una transacción por su hash de transacción, mostrado previamente en txid, con el comando gettransaction:

{

"amount" : 0.05000000,

"confirmations" : 0,

"txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",

"time" : 1392660908,

"timereceived" : 1392660908,

"details" : [

{

"account" : "",

"address" : "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",

"category" : "receive",

"amount" : 0.05000000

}

]

}

Las ID de transacción no son oficiales hasta que una transacción se confirma. No tener hash de transacción no quiere decir que la transacción no haya sido procesada. Esto se conoce como «maleabilidad de transacciones», porque los hashes de transacción pueden ser modificados anteriormente a la confirmación del bloque. Después de la confirmación, el txid es inmutable y oficial.

La forma de transacción mostrada con el comando gettransaction es la forma simplificada. Para conseguir la transacción completa y descodificarla, usaremos dos comandos: getrawtransaction y decoderawtransaction. Previamente, getrawtransaction lleva el hash de transacción (txid) como un parámetro y devuelve la transacción completa como una cadena hexadecimal en bruto, exactamente como existe en la red bitcoin:

Para decodificar esta cadena hexadecimal, usaremos decoderawtransaction. Copiar y pegar el hexadecimal como primer parámetro de decoderawtransaction para obtener el contenido completo interpretado como una estructura de datos JSON (por razones de formato la cadena hexadecimal se acorta en el siguiente ejemplo):

La decodificación de la transacción muestra todos los componentes de la transacción, incluyendo las entradas y salidas de la transacción. En este caso vemos que la transacción que acredita nuestra nueva dirección con 50 milibitcoins usa una entrada (input) y ha generado dos salidas (outputs). La entrada a esta transacción fue la salida de una previa transacción confirmada (mostrada como el vin txid que empieza con d3c7). Las dos salidas corresponden a 50 milibitcoins de crédito y la salida con cambio para el emisor.

Podemos explorar posteriormente la cadena de bloques examinando la transacción previa referida por su txid en esta transacción usando los mismos comandos (e.g., gettransaction). Saltando de transacción en transacción podemos seguir una cadena de transacciones hacia atrás a medida que las monedas se transmiten de la dirección de un propietario a la dirección a otro propietario.

Una vez que la transacción que hemos recibido ha sido confirmada incluyéndose en un bloque, el comando gettransaction devolverá información adicional, mostrando el hash de bloque (identificador) en el que se ha incluido la transacción:

Aquí, vemos la nueva información en las entradas blockhash (el hash del bloque en que ha sido incluida la transacción), y blockindex con el valor 18 (indicando que nuestra transacción fue la transacción en la posición 18 de ese bloque).

Índice de base de datos de transacción y opción txindex

Por defecto, Bitcoin Core construye una base de datos que contiene solamente las transacciones relacionadas con la cartera del usuario. Si desea acceder a cualquier transacción con comandos como gettransaction, necesita configurar Bitcoin Core para que construya un índice de transacciones completo, lo cual se consigue con la opción txindex. Establezca txindex=1 en el fichero de configuración de Bitcoin Core (normalmente se encuentra en .bitcoin/bitcoin.conf del directorio home). Una vez que haya modificado este parámetro, es necesario que reinicie bitcoind y espere a que se reconstruya el índice.

Explorando Bloques

Comandos: getblock, getblockhash

Ahora que sabemos en qué bloque fue incluida nuestra transacción, podemos consultar dicho bloque.

Usamos el comando getblock con el hash del bloque como parámetro:

El bloque contiene 367 transacciones y, como puede observar, la transacción listada en la posición (9ca8f9…) es la txid de la que acredita 50 millibits (1 millibit son 0.001 bitcoins) a nuestra dirección. La altura (height) nos dice que este es el bloque número 286384 en la cadena de bloques.

También podemos recuperar datos de un bloque por su altura usando el comando getblockhash, el cual toma la altura del bloque como parámetro y devuelve el hash de bloque para ese bloque: Aquí recuperamos el hash de bloque del «bloque génesis», el primer bloque minado por Satoshi Nakamoto, con altura cero. Recuperar este bloque muestra:

Los comandos getblock, getblockhash y gettransaction pueden usarse para explorar la base de datos de la cadena de bloques escribiendo código de programación:

Creando, Firmando y Enviando Transacciones Basadas en Salidas Sin Gastar

Comandos: listunspent, gettxout, createrawtransaction, decoderawtransaction, signrawtransaction, sendrawtransaction

Las transacciones en bitcoin se basan en el concepto de «salidas», las cuales son el resultado de transacciones previas, para crear una cadena de transacciones que transfiere propiedad de dirección en dirección. Nuestra cartera ahora ha recibido una transacción que asigna una salida a nuestra dirección. Una vez confirmada podemos gastar esa salida.

Primero utilizamos el comando listunspent para mostrar todas las salidas confirmadas sin gastar en nuestra cartera:

$ bitcoin-cli listunspent

[

{

"txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",

"vout" : 0,

"address" : "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",

"account" : "",

"scriptPubKey" : "76a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac",

"amount" : 0.05000000,

"confirmations" : 7

}

]

Vemos que la transacción 9ca8f9… creó una salida (con índice 0) asignada a la dirección 1hvzSo… por el monto de 50 milibitcoins, la cual a este punto ha recibido siete confirmaciones. Las transacciones utilizan salidas creadas previamente como sus entradas refiriéndose a ellas por el txid e índice de vout previos. Ahora crearemos una transacción que gastará el vout 0-ésimo de la transacción 9ca8f9… como su entrada y la asignará a una nueva salida que envíe el valor a una nueva dirección.

Primero observemos esta salida específica en mayor detalle. Usamos gettxout para obtener los detalles de esta salida sin gastar.

Las salidas de transacciones son siempre referenciadas por txid y vout, y éstos son los parámetros que pasamos a gettxout:

Lo que vemos aquí es la salida que asignó 50 milibitcoins a nuestra dirección 1hvz…. Para gastar esta salida debemos crear una nueva transacción. Primero creemos una dirección a la cual enviaremos el dinero:

$ bitcoin-cli getnewaddress

1LnfTndy3qzXGN19Jwscj1T8LR3MVe3JDb

Enviaremos 25 milibitcoins a la nueva dirección 1LnfTn… que acabamos de crear en nuestra cartera. En nuestra nueva transacción gastaremos una salida de 50 milibitcoins y enviaremos 25 milibitcoins a esta nueva dirección. Ya que tenemos que gastar la salida de la transacción previa entera, también tendremos que generar cambio. Generaremos el cambio de regreso a la dirección 1hvz…, enviando el cambio de vuelta a la dirección de la cual sale el valor originalmente. Finalmente también tendremos que pagar una pequeña comisión por esta transacción. Para pagar la comisión debemos reducir la salida del cambio en 0.5 milibitcoins y devolver 24,5 milibitcoins de cambio. La diferencia entre la suma de las nuevas salidas (25 mBTC + 24,5 mBTC = 49,5 mBTC) y la entrada (50 mBTC) será recolectada por los mineros como la comisión de transacción.

Usamos createarawtransaction para crear esta transacción. Como parámetros para createrawtransaction proporcionamos la entrada de la transacción (la salida sin gastar de 50 milibitcoins de nuestra transacción confirmada) y las dos salidas de la transacción (dinero enviado a la nueva dirección y cambio enviado de vuelta a la dirección previa):

El comando createrawtransaction produce una cadena hexadecimal en crudo que codifica los detalles de transacción que hemos provisto. Confirmemos que todo esté correcto decodificando esta cadena en crudo usando el comando decoderawtransaction:

¡Eso se ve correcto! Nuestra nueva transacción «consume» la salida sin gastar de nuestra transacción confirmada y luego la gasta en dos salidas, una por 25 milibitcoins a nuestra nueva dirección y una por 24,5 milibitcoins como cambio de regreso a la dirección original. La diferencia de 0,5 milibitcoins representa la comisión de transacción y será acreditada al minero que encuentre el bloque que incluye nuestra transacción.

Como puede haber notado, la transacción contiene un scriptSig vacío ya que no la hemos firmado aun.

Sin una firma esta transacción carece de significado; no hemos aún probado que la dirección de la cual proviene la salida sin gastar nos pertenece. Al firmar removemos el candado sobre la salida y probamos que somos dueños de esta salida y podemos gastarla. Usamos el comando signrawtransaction para firmar la transacción. El comando toma la cadena hexadecimal de la transacción en crudo como parámetro:

Una cartera encriptada debe ser abierta antes de que la transacción sea firmada ya que firmar requiere de acceso a las claves secretas en la cartera.

El comando signrawtransasction devuelve otra transacción en crudo codificada en hexadecimal. La decodificamos para ver qué ha cambiado con decoderawtransaction:

Ahora las entradas usadas en la transacción contienen un scriptSig, el cual es una firma digital probando la pertenencia de la dirección 1hvz… y removiendo el cerrojo sobre la salida para que pueda ser gastada. La firma hace a esta transacción verificable por cualquier nodo en la red bitcoin.

Ahora es tiempo de enviar la transacción recientemente creada a la red. Hacemos esto con el comando sendrawtransaction, el cual toma la cadena hexadecimal en crudo producida por signrawtransaction.

Esta es la misma cadena que acabamos de decodificar:

El comando sendrawtransaction devuelve un hash de transacción (txid) y envía la transacción a la red.

Ahora podemos consultar ese ID de transacción con gettransaction:

{

   "amount" : 0.00000000,

   "fee" : -0.00050000,

   "confirmations" : 0,

   "txid" : "ae74538baa914f3799081ba78429d5d84f36a0127438e9f721dff584ac17b346",

   "time" : 1392666702,

   "timereceived" : 1392666702,

   "details" : [

         {

         "account" : "",

         "address" : "1LnfTndy3qzXGN19Jwscj1T8LR3MVe3JDb",

         "category" : "send",

         "amount" : -0.02500000,

         "fee" : -0.00050000

      },

      {

         "account" : "",

         "address" : "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",

         "category" : "send",

         "amount" : -0.02450000,

         "fee" : -0.00050000

      },

      {

         "account" : "",

         "address" : "1LnfTndy3qzXGN19Jwscj1T8LR3MVe3JDb",

         "category" : "receive",

         "amount" : 0.02500000

      },

      {

         "account" : "",

         "address" : "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",

         "category" : "receive",

         "amount" : 0.02450000

      }

   ]

}

Al igual que antes, podemos examinar esto en mayor detalle usando los comandos getrawtransaction y decoderawtransaction. Estos comandos devolverán la misma cadena hexadecimal que hemos producido y decodificado previamente a enviarla a la red.

Ir a la siguiente página

Report Page