mirror of
				https://github.com/ChristopherA/Learning-Bitcoin-from-the-Command-Line.git
				synced 2025-11-04 04:17:43 +00:00 
			
		
		
		
	Merge pull request #365 from javiervargas/patch-51
Chapter 18-4 18_4_Accediendo_a_Bitcoind_con_Python.md
This commit is contained in:
		
						commit
						14440544b1
					
				
							
								
								
									
										464
									
								
								es/18_4_Accediendo_a_Bitcoind_con_Python.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										464
									
								
								es/18_4_Accediendo_a_Bitcoind_con_Python.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,464 @@
 | 
				
			|||||||
 | 
					# 18.4: Acceso a Bitcoind con Python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> :information_source: **NOTA:** Esta sección se ha añadido recientemente al curso y es un borrador temprano que todavía puede estar pendiente de revisión. Lectura con advertencias
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Esta sección explica cómo interactuar con `bitcoind` usando el lenguaje de programación Python y el paquete [Python-BitcoinRPC](https://github.com/jgarzik/python-bitcoinrpc).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Configuración de Python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Si usted ya tiene Bitcoin Core instalado, debería tener Python 3 disponible también.
 | 
				
			||||||
 | 
					Puede comprobar esto corriendo:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`$ python3 --version`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Si devuelve un número de versión (por ejemplo, `3.7.3` o `3.8.3`) entonces tiene python3 instalado.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sin embargo, si de alguna manera no tiene Python instalado, necesitará construirlo desde el código fuente como sigue. Consulte la variante ["Compilando python desde la fuente"](18_4_Accediendo_a_Bitcoind_con_Python.md#variant-build-python-from-source) antes de continuar.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Configurar BitcoinRPC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ya sea que haya usado un Python existente o lo haya compilado desde el código fuente, ahora usted esta listo para instalar la biblioteca `python-bitcoinrpc` :
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					$ pip3 install python-bitcoinrpc
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Si no tiene `pip` instalado, necesitará ejecutar lo siguiente:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					$ sudo apt install python3-pip
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					(A continuación, repita las instrucciones `pip3 install python-bitcoinrpc` .)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Crear un proyecto BitcoinRPC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Generalmente necesitara incluir declaraciones apropiadas de `bitcoinrpc` en sus proyectos de Bitcoin en Python. Lo siguiente le dará acceso a los comandos basados en RPC:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					También puede encontrar útil lo siguiente:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					from pprint import pprint
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					`pprint` imprimirá amigablemente la respuesta `json` de `bitcoind`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`logging` imprimirá la llamada que haga a `bitcoind` y la respuesta de `bitcoind`, lo cual es útil cuando hace un montón de llamadas juntas. Si no quiere que la salida excesiva se muestre en el terminal sólo debe comentar el bloque `logging` .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Construya su conexión
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ahora está listo para empezar a interactuar con `bitcoind` estableciendo una conexión. Cree un archivo llamado `btcrpc.py` y escriba lo siguiente:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					logging.basicConfig()
 | 
				
			||||||
 | 
					logging.getLogger("BitcoinRPC").setLevel(logging.DEBUG)
 | 
				
			||||||
 | 
					# rpc_user and rpc_password are set in the bitcoin.conf file
 | 
				
			||||||
 | 
					rpc_user = "StandUp"
 | 
				
			||||||
 | 
					rpc_pass = "6305f1b2dbb3bc5a16cd0f4aac7e1eba"
 | 
				
			||||||
 | 
					rpc_host = "127.0.0.1"
 | 
				
			||||||
 | 
					rpc_client = AuthServiceProxy(f"http://{rpc_user}:{rpc_pass}@{rpc_host}:18332", timeout=120)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Los argumentos en la URL son `rpc_username>:rpc_password>@host_IP_address>:port>`. Como de costumbre, el usuario `user` y `pass` se encuentran en su `~/. bitcoin/bitcoin.conf`, mientras que el `host` es su maquina local, y el puerto es `18332` para testnet. El argumento `timeout` se especifica desde _sockets timeout_ bajo carga pesada en la red principal. Si obtiene `socket.timeout: timed out` response, sea paciente y aumente el `timeout`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> :link: **MAINNET VS TESTNET:** El puerto sería 8332 para una configuración de mainnet.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Hacer una llamada RPC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Si `rpc_client` se inicializa correctamente, podrá enviar comandos RPC a su nodo bitcoin.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Para usar un método RPC desde `python-bitcoinrpc`, usará el objeto `rpc_client` que creó, que proporciona la mayor parte de la funcionalidad a la que se puede acceder a través de `bitcoin-cli`, usando los mismos nombres de método.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Por ejemplo, lo siguiente recuperará el conteo de bloques de su nodo:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					block_count = rpc_client.getblockcount()
 | 
				
			||||||
 | 
					print("---------------------------------------------------------------")
 | 
				
			||||||
 | 
					print("Block Count:", block_count)
 | 
				
			||||||
 | 
					print("---------------------------------------------------------------\n")
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Debería ver la siguiente salida con `logging` activado :
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					DEBUG:BitcoinRPC:-3-> getblockcount []
 | 
				
			||||||
 | 
					DEBUG:BitcoinRPC:<-3- 1773020
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					Block Count: 1773020
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					### Hacer una llamada RPC con argumentos
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Puede usar ese conteo de bloques como argumento para recuperar el blockhash de un bloque y también para recuperar detalles de ese bloque.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Esto se hace enviando los comandos objeto `rpc_client` con un argumento:
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					blockhash = rpc_client.getblockhash(block_count)
 | 
				
			||||||
 | 
					block = rpc_client.getblock(blockhash)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					El `getblockhash` devolverá un solo valor, mientras que el `getblock` devolverá un array asociativo de información sobre el bloque, que incluye un array bajo `block['tx']` proporcionando detalles sobre cada transacción dentro del bloque:
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					nTx = block['nTx']
 | 
				
			||||||
 | 
					if nTx > 10:
 | 
				
			||||||
 | 
					    it_txs = 10
 | 
				
			||||||
 | 
					    list_tx_heading = "First 10 transactions: "
 | 
				
			||||||
 | 
					else:
 | 
				
			||||||
 | 
					    it_txs = nTx
 | 
				
			||||||
 | 
					    list_tx_heading = f"All the {it_txs} transactions: "
 | 
				
			||||||
 | 
					print("---------------------------------------------------------------")
 | 
				
			||||||
 | 
					print("BLOCK: ", block_count)
 | 
				
			||||||
 | 
					print("-------------")
 | 
				
			||||||
 | 
					print("Block Hash...: ", blockhash)
 | 
				
			||||||
 | 
					print("Merkle Root..: ", block['merkleroot'])
 | 
				
			||||||
 | 
					print("Block Size...: ", block['size'])
 | 
				
			||||||
 | 
					print("Block Weight.: ", block['weight'])
 | 
				
			||||||
 | 
					print("Nonce........: ", block['nonce'])
 | 
				
			||||||
 | 
					print("Difficulty...: ", block['difficulty'])
 | 
				
			||||||
 | 
					print("Number of Tx.: ", nTx)
 | 
				
			||||||
 | 
					print(list_tx_heading)
 | 
				
			||||||
 | 
					print("---------------------")
 | 
				
			||||||
 | 
					i = 0
 | 
				
			||||||
 | 
					while i < it_txs:
 | 
				
			||||||
 | 
					    print(i, ":", block['tx'][i])
 | 
				
			||||||
 | 
					    i += 1
 | 
				
			||||||
 | 
					print("---------------------------------------------------------------\n")
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					### Ejecute su código
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Puede recuperar [el código fuente en](src/17_4_getinfo.py) y ejecutarlo con `python3`:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					$ python3 getinfo.py
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					Block Count: 1831106
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					BLOCK:  1831106
 | 
				
			||||||
 | 
					-------------
 | 
				
			||||||
 | 
					Block Hash...:  00000000000003b2ea7c2cdfffd86156ad1f5606ab58e128940a2534d1348b04
 | 
				
			||||||
 | 
					Merkle Root..:  056a547fe59208167eef86fa694263728fb684119254b340c1f86bdd423a8082
 | 
				
			||||||
 | 
					Block Size...:  52079
 | 
				
			||||||
 | 
					Block Weight.:  128594
 | 
				
			||||||
 | 
					Nonce........:  1775583700
 | 
				
			||||||
 | 
					Difficulty...:  4194304
 | 
				
			||||||
 | 
					Number of Tx.:  155
 | 
				
			||||||
 | 
					First 10 transactions: 
 | 
				
			||||||
 | 
					---------------------
 | 
				
			||||||
 | 
					0 : d228d55112e3aa26265b0118cfdc98345c229d20fe074b9afb87107c03ce11b5
 | 
				
			||||||
 | 
					1 : 92822e8e34fafb472b87c99ea3f3e16440452b3f361ed86c6fa62175173fb750
 | 
				
			||||||
 | 
					2 : fa7c67600c14d4aa350a9674688f1429577954f4a6c5e4639d06c8964824f647
 | 
				
			||||||
 | 
					3 : 3a91d1527e308e5603dafde7ab17824f441a73a779d2571d073466dc9e8451b2
 | 
				
			||||||
 | 
					4 : 30fd0e5527b1522e7b26a4818b9edac80fe47c0c39fc34705478a49e684708d0
 | 
				
			||||||
 | 
					5 : 24c5372b38c78cbaf5b0b305925502a491bc0c1b5758f50c0bd335abb6ae85f5
 | 
				
			||||||
 | 
					6 : be70e125a5793efc5e32051fecba0668df971bdf371138c8261201c2a46b2d38
 | 
				
			||||||
 | 
					7 : 41ebf52c847a59ba0aeb4425c74e89a01e91defa86a82785ff53ed4668054561
 | 
				
			||||||
 | 
					8 : dc8211b4ce122f87692e7c203672e3eb1ffc44c0a307eafcc560323fcc5fae78
 | 
				
			||||||
 | 
					9 : 59e2d8e11cad287eacf3207e64a373f65059286b803ef0981510193ae29cbc8c
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					## Buscar fondos
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Del mismo modo, puede recuperar la información de su cartera con el `getwalletinfo` RPC:
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					wallet_info = rpc_client.getwalletinfo()
 | 
				
			||||||
 | 
					print("---------------------------------------------------------------")
 | 
				
			||||||
 | 
					print("Wallet Info:")
 | 
				
			||||||
 | 
					print("-----------")
 | 
				
			||||||
 | 
					pprint(wallet_info)
 | 
				
			||||||
 | 
					print("---------------------------------------------------------------\n")
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Debería tener una salida similar a la siguiente con `logging` disabled:
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					Wallet Info:
 | 
				
			||||||
 | 
					-----------
 | 
				
			||||||
 | 
					{'avoid_reuse': False,
 | 
				
			||||||
 | 
					 'balance': Decimal('0.07160443'),
 | 
				
			||||||
 | 
					 'hdseedid': '6dko666b1cc0d69b7eb0539l89eba7b6390kdj02',
 | 
				
			||||||
 | 
					 'immature_balance': Decimal('0E-8'),
 | 
				
			||||||
 | 
					 'keypoololdest': 1542245729,
 | 
				
			||||||
 | 
					 'keypoolsize': 999,
 | 
				
			||||||
 | 
					 'keypoolsize_hd_internal': 1000,
 | 
				
			||||||
 | 
					 'paytxfee': Decimal('0E-8'),
 | 
				
			||||||
 | 
					 'private_keys_enabled': True,
 | 
				
			||||||
 | 
					 'scanning': False,
 | 
				
			||||||
 | 
					 'txcount': 9,
 | 
				
			||||||
 | 
					 'unconfirmed_balance': Decimal('0E-8'),
 | 
				
			||||||
 | 
					 'walletname': '',
 | 
				
			||||||
 | 
					 'walletversion': 169900}
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Otros comandos informativos como `getblockchaininfo`, `getnetworkinfo`, `getpeerinfo`, y `getblockchaininfo` funcionarán de manera similar.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Otros comandos pueden darle información específica sobre determinados elementos dentro de su cartera.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Recuperar una matriz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					La llamada RPC `listtransactions` le permite ver las 10 transacciones más recientes en su sistema (o algún conjunto arbitrario de transacciones usando los argumentos `count` y `skip` ). Muestra cómo un comando RPC puede devolver una matriz fácil de manipular:
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					tx_list = rpc_client.listtransactions()
 | 
				
			||||||
 | 
					pprint(tx_list)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					### Explorar un UTXO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Del mismo modo, puede utilizar `listunspent` para obtener una matriz de UTXOs en su sistema:
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					print("Exploring UTXOs")
 | 
				
			||||||
 | 
					## List UTXOs
 | 
				
			||||||
 | 
					utxos = rpc_client.listunspent()
 | 
				
			||||||
 | 
					print("Utxos: ")
 | 
				
			||||||
 | 
					print("-----")
 | 
				
			||||||
 | 
					pprint(utxos)
 | 
				
			||||||
 | 
					print("------------------------------------------\n")
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Con el fin de manipular un array como el devuelto desde `listtransactions`o `listunpsent`, sólo tiene que tomar el elemento apropiado del elemento apropiado del array:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					## Select a UTXO - first one selected here
 | 
				
			||||||
 | 
					utxo_txid = utxos[0]['txid']
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Para `listunspent`, se obtiene un `txid`. Puede recuperar información sobre él con `gettransaction`, luego decodificar eso con `decoderawtransaction`:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					utxo_hex = rpc_client.gettransaction(utxo_txid)['hex']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					utxo_tx_details = rpc_client.decoderawtransaction(utxo_hex)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("Details of Utxo with txid:", utxo_txid)
 | 
				
			||||||
 | 
					print("---------------------------------------------------------------")
 | 
				
			||||||
 | 
					print("UTXO Details:")
 | 
				
			||||||
 | 
					print("------------")
 | 
				
			||||||
 | 
					pprint(utxo_tx_details)
 | 
				
			||||||
 | 
					print("---------------------------------------------------------------\n")
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Este código está disponible en [walletinfo.py](src/17_4_walletinfo.py).
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					$ python3 walletinfo.py 
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					Wallet Info:
 | 
				
			||||||
 | 
					-----------
 | 
				
			||||||
 | 
					{'avoid_reuse': False,
 | 
				
			||||||
 | 
					 'balance': Decimal('0.01031734'),
 | 
				
			||||||
 | 
					 'hdseedid': 'da5a1b058deb9e51ecffef1b0ddc069a5dfb2c5f',
 | 
				
			||||||
 | 
					 'immature_balance': Decimal('0E-8'),
 | 
				
			||||||
 | 
					 'keypoololdest': 1596567843,
 | 
				
			||||||
 | 
					 'keypoolsize': 1000,
 | 
				
			||||||
 | 
					 'keypoolsize_hd_internal': 999,
 | 
				
			||||||
 | 
					 'paytxfee': Decimal('0E-8'),
 | 
				
			||||||
 | 
					 'private_keys_enabled': True,
 | 
				
			||||||
 | 
					 'scanning': False,
 | 
				
			||||||
 | 
					 'txcount': 6,
 | 
				
			||||||
 | 
					 'unconfirmed_balance': Decimal('0E-8'),
 | 
				
			||||||
 | 
					 'walletname': '',
 | 
				
			||||||
 | 
					 'walletversion': 169900}
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Utxos: 
 | 
				
			||||||
 | 
					-----
 | 
				
			||||||
 | 
					[{'address': 'mv9cjEnS2o1EygBMdrz99LzhM8KeEMoXDg',
 | 
				
			||||||
 | 
					  'amount': Decimal('0.00001000'),
 | 
				
			||||||
 | 
					  'confirmations': 1180,
 | 
				
			||||||
 | 
					  'desc': "pkh([ce0c7e14/0'/0'/25']02d0541b9211aecd25913f7fdecfc1b469215fa326d52067b1b3f7efbd12316472)#n06pq9q5",
 | 
				
			||||||
 | 
					  'label': '-addresstype',
 | 
				
			||||||
 | 
					  'safe': True,
 | 
				
			||||||
 | 
					  'scriptPubKey': '76a914a080d1a10f5e7a02d0a291f118982ed19e8cfcd788ac',
 | 
				
			||||||
 | 
					  'solvable': True,
 | 
				
			||||||
 | 
					  'spendable': True,
 | 
				
			||||||
 | 
					  'txid': '84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e',
 | 
				
			||||||
 | 
					  'vout': 0},
 | 
				
			||||||
 | 
					 {'address': 'tb1qrcf8c29966tvqxhwrtd2se3rj6jeqtll3r46a4',
 | 
				
			||||||
 | 
					  'amount': Decimal('0.01029734'),
 | 
				
			||||||
 | 
					  'confirmations': 1180,
 | 
				
			||||||
 | 
					  'desc': "wpkh([ce0c7e14/0'/1'/26']02c581259ba7e6aef6d7ea23adb08f7c7f10c4c678f2e097a4074639e7685d4805)#j3pctfhf",
 | 
				
			||||||
 | 
					  'safe': True,
 | 
				
			||||||
 | 
					  'scriptPubKey': '00141e127c28a5d696c01aee1adaa8662396a5902fff',
 | 
				
			||||||
 | 
					  'solvable': True,
 | 
				
			||||||
 | 
					  'spendable': True,
 | 
				
			||||||
 | 
					  'txid': '84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e',
 | 
				
			||||||
 | 
					  'vout': 1},
 | 
				
			||||||
 | 
					 {'address': 'mzDxbtYY3LBBBJ6HhaBAtnHv6c51BRBTLE',
 | 
				
			||||||
 | 
					  'amount': Decimal('0.00001000'),
 | 
				
			||||||
 | 
					  'confirmations': 1181,
 | 
				
			||||||
 | 
					  'desc': "pkh([ce0c7e14/0'/0'/23']0377bdd176f985b4af2f6bdbb22c2925b6007b6c07ba171f75e65990c002615e98)#3y6ef6vu",
 | 
				
			||||||
 | 
					  'label': '-addresstype',
 | 
				
			||||||
 | 
					  'safe': True,
 | 
				
			||||||
 | 
					  'scriptPubKey': '76a914cd339342b06042bb986a45e73d56db46acc1e01488ac',
 | 
				
			||||||
 | 
					  'solvable': True,
 | 
				
			||||||
 | 
					  'spendable': True,
 | 
				
			||||||
 | 
					  'txid': '1679bee019c61608340b79810377be2798efd4d2ec3ace0f00a1967af70666b9',
 | 
				
			||||||
 | 
					  'vout': 1}]
 | 
				
			||||||
 | 
					------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Details of Utxo with txid: 84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					UTXO Details:
 | 
				
			||||||
 | 
					------------
 | 
				
			||||||
 | 
					{'hash': '0c6c27f58f122329bbc53a91f290b35ce23bd2708706b21a04cdc387dc8e2fd9',
 | 
				
			||||||
 | 
					 'locktime': 1831103,
 | 
				
			||||||
 | 
					 'size': 225,
 | 
				
			||||||
 | 
					 'txid': '84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e',
 | 
				
			||||||
 | 
					 'version': 2,
 | 
				
			||||||
 | 
					 'vin': [{'scriptSig': {'asm': '', 'hex': ''},
 | 
				
			||||||
 | 
					          'sequence': 4294967294,
 | 
				
			||||||
 | 
					          'txid': '1679bee019c61608340b79810377be2798efd4d2ec3ace0f00a1967af70666b9',
 | 
				
			||||||
 | 
					          'txinwitness': ['3044022014b3e2359fb46d8cbc4cd30fa991b455edfa4b419a4c64a53fcdfc79e3ca89db022010cefc3268bc252d55f1982c426328b709b47d02332def9e2efb3b12de2cf0d301',
 | 
				
			||||||
 | 
					                          '0351b470e87b44e8e9607acf09b8d4543c51c93c17dc741176319e60202091f2be'],
 | 
				
			||||||
 | 
					          'vout': 0}],
 | 
				
			||||||
 | 
					 'vout': [{'n': 0,
 | 
				
			||||||
 | 
					           'scriptPubKey': {'addresses': ['mv9cjEnS2o1EygBMdrz99LzhM8KeEMoXDg'],
 | 
				
			||||||
 | 
					                            'asm': 'OP_DUP OP_HASH160 '
 | 
				
			||||||
 | 
					                                   'a080d1a10f5e7a02d0a291f118982ed19e8cfcd7 '
 | 
				
			||||||
 | 
					                                   'OP_EQUALVERIFY OP_CHECKSIG',
 | 
				
			||||||
 | 
					                            'hex': '76a914a080d1a10f5e7a02d0a291f118982ed19e8cfcd788ac',
 | 
				
			||||||
 | 
					                            'reqSigs': 1,
 | 
				
			||||||
 | 
					                            'type': 'pubkeyhash'},
 | 
				
			||||||
 | 
					           'value': Decimal('0.00001000')},
 | 
				
			||||||
 | 
					          {'n': 1,
 | 
				
			||||||
 | 
					           'scriptPubKey': {'addresses': ['tb1qrcf8c29966tvqxhwrtd2se3rj6jeqtll3r46a4'],
 | 
				
			||||||
 | 
					                            'asm': '0 1e127c28a5d696c01aee1adaa8662396a5902fff',
 | 
				
			||||||
 | 
					                            'hex': '00141e127c28a5d696c01aee1adaa8662396a5902fff',
 | 
				
			||||||
 | 
					                            'reqSigs': 1,
 | 
				
			||||||
 | 
					                            'type': 'witness_v0_keyhash'},
 | 
				
			||||||
 | 
					           'value': Decimal('0.01029734')}],
 | 
				
			||||||
 | 
					 'vsize': 144,
 | 
				
			||||||
 | 
					 'weight': 573}
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					## Crear una dirección
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Crear una nueva dirección con Python 3 solo requiere el uso de un RPC como `getnewaddress` o `getrawchangeaddress`.
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					new_address = rpc_client.getnewaddress("Learning-Bitcoin-from-the-Command-Line")
 | 
				
			||||||
 | 
					new_change_address = rpc_client.getrawchangeaddress()
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					En este ejemplo, se da el comando `getnewaddress` un argumento: la etiqueta `Learning-Bitcoin-from-the-Command-Line` .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Enviar una transacción
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Crear una transacción en Python 3 requiere combinar algunos de los ejemplos anteriores (de crear direcciones y recuperar UTXOs) con algunos nuevos comandos RPC para crear, firmar y enviar una transacción mucho de lo que ha hecho anteriormente desde la línea de comandos.
 | 
				
			||||||
 | 
					Hay cinco pasos a seguir:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					0. Crear dos direcciones, una que actuará como receptor y la otra para el cambio.
 | 
				
			||||||
 | 
					1. Seleccione un UTXO y establezca los detalles de la transacción.
 | 
				
			||||||
 | 
					2. Crear una transacción en bruto.
 | 
				
			||||||
 | 
					3. Firmar la transacción en bruto con la clave privada de la UTXO.
 | 
				
			||||||
 | 
					4. Difundir la transacción en el bitcoin testnet.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 1. Seleccione UTXO y definir los detalles de la transacción
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					En el siguiente fragmento de código, primero seleccione el UTXO que queremos gastar. Entonces usted consigue su dirección, la identificación de la transacción, y el índice vectorial de la salida.
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					utxos = rpc_client.listunspent()
 | 
				
			||||||
 | 
					selected_utxo = utxos[0]  # again, selecting the first utxo here
 | 
				
			||||||
 | 
					utxo_address = selected_utxo['address']
 | 
				
			||||||
 | 
					utxo_txid = selected_utxo['txid']
 | 
				
			||||||
 | 
					utxo_vout = selected_utxo['vout']
 | 
				
			||||||
 | 
					utxo_amt = float(selected_utxo['amount'])
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					A continuación, también recupera la dirección del destinatario a la que quiere enviar los bitcoins, calcula la cantidad de bitcoins que quiere enviar, y calcula la tarifa minera y la cantidad de cambio. Aquí, la cantidad se divide arbitrariamente en dos y una cuota de minero se establece arbitrariamente.
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					recipient_address = new_address
 | 
				
			||||||
 | 
					recipient_amt = utxo_amt / 2  # sending half coins to recipient
 | 
				
			||||||
 | 
					miner_fee = 0.00000300        # choose appropriate fee based on your tx size
 | 
				
			||||||
 | 
					change_address = new_change_address
 | 
				
			||||||
 | 
					change_amt = float('%.8f'%((utxo_amt - recipient_amt) - miner_fee))
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					> :warning: **WARNING:** Obviamente un programa real tomaría decisiones más sofisticadas sobre qué UTXO usar, qué hacer con los fondos, y qué cuota de minero pagar.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 2. Crear transacciones sin procesar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ahora usted tiene toda la información para enviar una transacción, pero antes de que pueda enviar una, tiene que crear una transacción.
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					txids_vouts = [{"txid": utxo_txid, "vout": utxo_vout}]
 | 
				
			||||||
 | 
					addresses_amts = {f"{recipient_address}": recipient_amt, f"{change_address}": change_amt}
 | 
				
			||||||
 | 
					unsigned_tx_hex = rpc_client.createrawtransaction(txids_vouts, addresses_amts)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Recuerde que el formato del comando `createrawtransaction` es:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`$ bitcoin-cli createrawtransaction '[{"txid": <utxo_txid>, "vout": <vector_id>}]' '{"<address>": <amount>}'`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					El `txids_vouts` es así una lista y el `addresses_amts` es un diccionario de python, para que coincida con el formato de `createrawtransaction`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Si quiere ver más sobre los detalles de la transacción que ha creado, puede usar `decoderawtransaction`, ya sea en Python 3 o con `bitcoin-cli`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 3. Firma la transacción cruda
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Firmar una transacción es a menudo la parte más complicada de enviar una transacción programáticamente. Aquí usted recupera una clave privada de una dirección con `dumpprivkey` y la coloca en una matriz:
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					address_priv_key = []  # list of priv keys of each utxo
 | 
				
			||||||
 | 
					address_priv_key.append(rpc_client.dumpprivkey(utxo_address))
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					A continuación, puede utilizar esa matriz (que debe contener las claves privadas de cada UTXO que se está gastando) para firmar su `unsigned_tx_hex`:
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					signed_tx = rpc_client.signrawtransactionwithkey(unsigned_tx_hex, address_priv_key)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Esto devuelve un objeto JSON con el hexadecimal de la transacción firmada, y si fue firmado completamente o no:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 4. Transacción de transmisión
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Por último, está listo para transmitir la transacción firmada en la red bitcoin:
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					send_tx = rpc_client.sendrawtransaction(signed_tx['hex'])
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					### Ejecute su código
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					El [código de ejemplo](src/17_4_sendtx.py) está lleno de sentencias `print` para demostrar todos los datos disponibles en cada punto:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					$ python3 sendtx.py 
 | 
				
			||||||
 | 
					Creating a Transaction
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					Transaction Details:
 | 
				
			||||||
 | 
					-------------------
 | 
				
			||||||
 | 
					UTXO Address.......:  mv9cjEnS2o1EygBMdrz99LzhM8KeEMoXDg
 | 
				
			||||||
 | 
					UTXO Txid..........:  84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e
 | 
				
			||||||
 | 
					Vector ID of Output:  0
 | 
				
			||||||
 | 
					UTXO Amount........:  1e-05
 | 
				
			||||||
 | 
					Tx Amount..........:  5e-06
 | 
				
			||||||
 | 
					Recipient Address..:  tb1qca0elxxqzw5xc0s3yq5qhapzzj90ka0zartu6y
 | 
				
			||||||
 | 
					Change Address.....:  tb1qrveukqrvqm9h6fua99xvcxgnvdx507dg8e8hrt
 | 
				
			||||||
 | 
					Miner Fee..........:  3e-06
 | 
				
			||||||
 | 
					Change Amount......:  2e-06
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					Unsigned Transaction Hex:  02000000015e53fb6f63b7defa28e61c28cfc3033361138a0d33dd1fad29ae58c6fe7f20840000000000ffffffff02f401000000000000160014c75f9f98c013a86c3e1120280bf422148afb75e2c8000000000000001600141b33cb006c06cb7d279d294ccc1913634d47f9a800000000
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					Signed Transaction: 
 | 
				
			||||||
 | 
					----------------------
 | 
				
			||||||
 | 
					{'complete': True,
 | 
				
			||||||
 | 
					 'hex': '02000000015e53fb6f63b7defa28e61c28cfc3033361138a0d33dd1fad29ae58c6fe7f2084000000006a47304402205da9b2234ea057c9ef3b7794958db6c650c72dedff1a90d2915147a5f6413f2802203756552aba0dd8ebd71b0f28341becc01b28d8b28af063d7c8ce89f9c69167f8012102d0541b9211aecd25913f7fdecfc1b469215fa326d52067b1b3f7efbd12316472ffffffff02f401000000000000160014c75f9f98c013a86c3e1120280bf422148afb75e2c8000000000000001600141b33cb006c06cb7d279d294ccc1913634d47f9a800000000'}
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---------------------------------------------------------------
 | 
				
			||||||
 | 
					TXID of sent transaction:  187f8baa222f9f37841d966b6bad59b8131cfacca861cbe9bfc8656bd16a44cc
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					## Resumen: Acceso a Bitcoind con Python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Acceder a Bitcoind con Python es muy fácil mientras usa la biblioteca `python-bitcoinrpc`. Lo primero que hay que hacer siempre es establecer una conexión con su `bitcoind` instancia, a continuación, puede llamar a todas las llamadas a la API de bitcoin como se describe en la documentación de núcleo de bitcoin. Esto hace que sea fácil crear programas pequeños o grandes para administrar su propio nodo, comprobar balances, o crear aplicaciones interesantes en la parte superior dado que tiene acceso a la potencia total de `bitcoin-cli`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ¿Qué es lo siguiente?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Obtén más información sobre "Cómo hablar con Bitcoin en otros lenguages" en [18.5: Cómo acceder a Bitcoin con Rust](18_5_Accediendo_a_Bitcoind_con_Rust.md).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Variante: Construir Python desde el Origen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Si necesita instalar Python 3 desde el código fuente, siga estas instrucciones y luego continúe con ["Creando un proyecto BitcoinRPC"](18_4_Accediendo_a_Bitcoind_con_Python.md#creating-a-bitcoinrpc-project).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 1. Instalar dependencias
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					$ sudo apt-get install build-essential checkinstall
 | 
				
			||||||
 | 
					$ sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					### 2. Descargar y extraer Python
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					$ wget https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz
 | 
				
			||||||
 | 
					$ tar -xzf Python-3.8.3.tgz
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					### 3. Compilar Python Origen & Comprobar instalación:
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					$ cd Python-3.8.3
 | 
				
			||||||
 | 
					$ sudo ./configure --enable-optimizations
 | 
				
			||||||
 | 
					$ sudo make -j 8  # enter the number of cores of your system you want to use to speed up the build process.
 | 
				
			||||||
 | 
					$ sudo make altinstall
 | 
				
			||||||
 | 
					$ python3.8 --version
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Después de obtener la salida de la versión, elimine el archivo de origen:
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					$ rm Python-3.8.3.tgz
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user