mirror of
https://github.com/ChristopherA/Learning-Bitcoin-from-the-Command-Line.git
synced 2025-06-07 16:06:26 +00:00
Merge pull request #393 from KoreaComK/chapter14
Chapter 14 Translated by @koreacomk need review
This commit is contained in:
commit
122dae075c
21
pt/14_0_Using_Tor.md
Normal file
21
pt/14_0_Using_Tor.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Capítulo 14: Usando o Tor
|
||||
|
||||
O Tor é um dos programas padrão instalados pelo [Bitcoin Standup](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts). Ele nos ajuda a manter nosso servidor seguro, o que é extremamente importante quando estamos lidando com Bitcoin. Este capítulo divaga um pouco do nosso objetivo para nos ajudar a entender essa infraestrutura de segurança.
|
||||
|
||||
## Objetivos deste Capítulo
|
||||
|
||||
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
|
||||
|
||||
* Usar uma configuração Tor;
|
||||
* Fazer a manutenção do Tor.
|
||||
|
||||
Os objetivos secundários incluem a capacidade de:
|
||||
|
||||
* Compreender a rede Tor;
|
||||
* Compreender as várias portas do Bitcoin.
|
||||
|
||||
## Tabela de Conteúdo
|
||||
|
||||
* [Seção 1: Verificando a Sua Configuração do Tor](14_1_Verifying_Your_Tor_Setup.md)
|
||||
* [Seção 2: Mudando os Seus Serviços Ocultos do Bitcoin](14_2_Changing_Your_Bitcoin_Hidden_Services.md)
|
||||
* [Seção 3: Adicionando um Serviço SSH Oculto](14_3_Adding_SSH_Hidden_Services.md)
|
365
pt/14_1_Verifying_Your_Tor_Setup.md
Normal file
365
pt/14_1_Verifying_Your_Tor_Setup.md
Normal file
@ -0,0 +1,365 @@
|
||||
# 14.1: Verificando a Configuração do Tor
|
||||
|
||||
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
|
||||
|
||||
Se fizéssemos uma instalação padrão com o [Bitcoin Standup](https://github.com/BlockchainCommons/Bitcoin-Standup), provavelmente já teríamos o Tor configurado como parte do nosso node Bitcoin. O Tor está instalado e já criou os serviços ocultos para as portas RPC do Bitcoin, enquanto um endereço Onion também foi criado para o ```bitcoind```. Nesta seção iremos discutir tudo isso e o que fazer com essas informações e ferramentas.
|
||||
|
||||
> :book: ***O que é o Tor?*** O Tor é uma rede de sobreposição e anonimato de baixa latência baseada no design de roteamento e construção de caminhos para permitir a comunicação anônima. É um software gratuito e open source com o nome derivado da sigla do nome do projeto de software original: "The Onion Router".
|
||||
|
||||
> :book: ***Por que usar o Tor com o Bitcoin?*** A rede Bitcoin é uma rede peer-to-peer que escuta as transações e as propaga usando um endereço IP público. Ao conectar-se à rede sem o Tor, iríamos compartilhar nosso endereço IP, o que poderia expor nossa localização, o tempo de atividade e outros detalhes a terceiros, o que é uma prática de privacidade indesejável. Para nos protegermos virtualmente, devemos usar ferramentas como o Tor para ocultar os detalhes da nossa conexão. O Tor permite melhorar nossa privacidade online, pois os dados são codificados criptograficamente e passam por nodes diferentes, cada um decodificando uma única camada (por isso a metáfora da cebola).
|
||||
|
||||
## Entendendo o Tor
|
||||
|
||||
Então, como o Tor funciona?
|
||||
|
||||
Quando um usuário deseja se conectar a um servidor na Internet, o Tor tenta construir um caminho formado por pelo menos três retransmissores de nodes do Tor, chamados de Guarda, Meio e Saída. Durante a construção desse caminho, as chaves de criptografia simétricas são negociadas. Quando uma mensagem se move ao longo do caminho, cada retransmissão remove sua camada de criptografia. Dessa forma, a mensagem chega ao destino final na forma original, e cada parte conhece apenas o salto anterior e o próximo e não pode determinar a origem ou o destino.
|
||||
|
||||
Esta é a aparência de uma conexão sem o Tor:
|
||||
```
|
||||
20:58:03.804787 IP bitcoin.36300 > lb-140-82-114-25-iad.github.com.443: Flags [P.], seq 1:30, ack 25, win 501, options [nop,nop,TS val 3087919981 ecr 802303366], length 29
|
||||
```
|
||||
Agora, com o Tor, muito menos informações sobre as máquinas reais são transmitidas:
|
||||
```
|
||||
21:06:52.744602 IP bitcoin.58776 > 195-xxx-xxx-x.rev.pxxxxxm.eu.9999: Flags [P.], seq 264139:265189, ack 3519373, win 3410, options [nop,nop,TS val 209009853 ecr 3018177498], length 1050
|
||||
21:06:52.776968 IP 195-xxx-xxx-x.rev.pxxxxxm.eu.9999 > bitcoin.58776: Flags [.], ack 265189, win 501, options [nop,nop,TS val 3018177533 ecr 209009853], length 0
|
||||
```
|
||||
Resumindo: o Tor criptografa nossos dados de forma a ocultar nossa origem, destino e quais serviços estamos usando, enquanto um protocolo de criptografia padrão como TLS *apenas* protege o conteúdo dos nossos dados.
|
||||
|
||||
### Compreendendo a Arquitetura da Rede Tor
|
||||
|
||||
A arquitetura básica da rede Tor é composta pelos seguintes componentes:
|
||||
|
||||
* **Cliente Tor (OP ou Onion Proxy).** Um cliente Tor instala o software local que atua como um proxy onion. Ele empacota os dados do aplicativo em células do mesmo tamanho (512 bytes), que então envia para a rede Tor. Uma célula é a unidade básica de transmissão do Tor.
|
||||
* **Node Onion (OR ou Onion Router).** Um Node Onion transmite células provenientes do cliente Tor e de servidores online. Existem três tipos de Nodes Onion: nodes de entrada (Guarda), nodes intermediários (Meio) e nodes de saída (Saída).
|
||||
* **Servidor de Diretório.** Um servidor de diretório armazena informações sobre roteadores e servidores onion (serviços ocultos), como as suas chaves públicas.
|
||||
* **Onion Server (Servidor Oculto).** Um servidor onion oferece suporte a aplicativos TCP, como páginas da web ou IRC, como serviços.
|
||||
|
||||
### Compreendendo as Limitações do Tor
|
||||
|
||||
O Tor não é uma ferramenta perfeita. Como as informações da rede Tor são descriptografadas nos nodes de saída antes de serem enviadas aos destinos finais, teoricamente um observador poderia coletar metadados suficientes para comprometer o anonimato e potencialmente identificar os usuários.
|
||||
|
||||
Também há estudos que sugerem que possíveis explorações da proteção anti-DoS do Bitcoin podem permitir que um invasor force outros usuários que usam o Tor a se conectar exclusivamente por meio dos nodes de saída do Tor ou dos seus pares Bitcoin, isolando o cliente do resto da rede Bitcoin e expondo-o a censura, correlação e demais ataques.
|
||||
|
||||
Da mesma forma, os usuários do Bitcoin Tor podem ser atacados por impressão digital (fingerprinting) definindo um cookie de endereço nos nodes. Isso também permitiria a correlação e, portanto, acabando com o anonimato.
|
||||
|
||||
Enquanto isso, mesmo no Tor, o Bitcoin é apenas um serviço pseudo-anônimo devido aos muitos perigos de correlação que se originam do próprio livro-razão permanente. Isso significa que o uso do Bitcoin sobre o Tor tem mais probabilidade de _perder o anonimato_ do que outros serviços (e pode levar ao anonimato de outras atividades).
|
||||
|
||||
Com isso dito, o Tor é geralmente considerado mais seguro do que a alternativa, que é a navegação não anônima.
|
||||
|
||||
## Verificando a Nossa Configuração do Tor
|
||||
|
||||
Então, como verificamos se o Tor está ativado? Se o instalamos com o Bitcoin Standup, podemos verificar se o Tor está sendo executado em nosso sistema:
|
||||
```
|
||||
$ sudo -u debian-tor tor --verify-config
|
||||
```
|
||||
|
||||
Se o Tor estiver instalado corretamente, devemos obter a seguinte resposta:
|
||||
```
|
||||
Jun 26 21:52:09.230 [notice] Tor 0.4.3.5 running on Linux with Libevent 2.0.21-stable, OpenSSL 1.0.2n, Zlib 1.2.11, Liblzma 5.2.2, and Libzstd N/A.
|
||||
Jun 26 21:52:09.230 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
|
||||
Jun 26 21:52:09.230 [notice] Read configuration file "/etc/tor/torrc".
|
||||
Configuration was valid
|
||||
```
|
||||
> :warning: **AVISO:** Isso significa apenas que o Tor está sendo executado, não que está sendo usado para todas (ou algumas) conexões.
|
||||
|
||||
### Verificando a Nossa Configuração do Tor para o RPC
|
||||
|
||||
O propósito mais importante do Tor, conforme instalado pelo Bitcoin Standup, é oferecer serviços ocultos para as portas RPC que são usadas para enviar comandos para o ```bitcoind```.
|
||||
|
||||
> :book: ***O que é um serviço oculto do Tor?*** Um serviço oculto (também conhecido como "um onion service") é um serviço que pode ser acessado via Tor. A conexão feita a esse serviço _usando a Onion Network_ será anônima.
|
||||
|
||||
O arquivo de configuração do Tor pode ser encontrado em ```/etc/tor/torrc```. Se olharmos para ele, veremos os seguintes serviços que protegem nossas portas do RPC:
|
||||
```
|
||||
HiddenServiceDir /var/lib/tor/standup/
|
||||
HiddenServiceVersion 3
|
||||
HiddenServicePort 1309 127.0.0.1:18332
|
||||
HiddenServicePort 1309 127.0.0.1:18443
|
||||
HiddenServicePort 1309 127.0.0.1:8332
|
||||
```
|
||||
> :link: **TESTNET vs MAINNET:** Na Mainnet o RPC é executado na porta 8332, já na testnet, na porta 18332.
|
||||
|
||||
> :information_source: **NOTA:** O ```HiddenServiceDir``` é onde todos os arquivos são mantidos para este serviço em particular. Se precisarmos pesquisar nosso endereço onion, chaves de acesso ou adicionar clientes autorizados, é aqui que iremos alterar!
|
||||
|
||||
A maneira fácil de testar o nosso Serviço Oculto RPC é usar o [QuickConnect API](https://github.com/BlockchainCommons/Bitcoin-Standup/blob/master/Docs/Quick-Connect-API.md) integrado ao Bitcoin Standup. Basta baixar o código QR que encontramos em ```/qrcode.png``` e digitalizá-lo usando uma carteira ou node que suporte o QuickConnect, como [a Gordian Wallet](https://github.com/BlockchainCommons/FullyNoded-2). Ao escanear o QR, devemos ver a carteira sincronizada com o nosso node. Estaremos fazendo isso usando os serviços ocultos do RPC.
|
||||
|
||||
A maneira difícil de testar nosso Serviço Oculto RPC é enviar um comando ```bitcoin-cli``` com o ```torify```, que permite traduzir um comando UNIX normal para um comando protegido por Tor. É algo difícil porque precisamos obter três informações.
|
||||
|
||||
1. **Nossa porta de serviço oculta.** Isso pode ser obtido em ```/etc/tor/torrc/```. Por padrão, é a porta 1309.
|
||||
2. **Nosso endereço Tor.** Essa informação encontra-se no arquivo ```hostname``` no diretório ```HiddenServiceDir``` definido em ```/etc/tor/torrc```. Por padrão, o arquivo pode ser encontrado em ```/var/lib/tor/standup/hostname```. Ele está protegido, então precisaremos usar o ```sudo``` para acessá-lo:
|
||||
```
|
||||
$ sudo more /var/lib/tor/standup/hostname
|
||||
mgcym6je63k44b3i5uachhsndayzx7xi4ldmwrm7in7yvc766rykz6yd.onion
|
||||
```
|
||||
3. **Nossa senha do RPC.** Que está no arquivo ```~/.bitcoin/bitcoin.conf```
|
||||
|
||||
Quando tivermos todas essas informações, podemos emitir um comando ```bitcoin-cli``` usando o ```torify``` e especificando o ```-rpcconnect``` como nosso endereço onion, o ```-rpcport``` como nossa porta de serviço oculta, e o ```-rpcpassword``` como sendo nossa senha:
|
||||
```
|
||||
$ torify bitcoin-cli -rpcconnect=mgcym6je63k44b3i5uachhsndayzx7xi4ldmwrm7in7yvc766rykz6yd.onion -rpcport=1309 -rpcuser=StandUp -rpcpassword=685316cc239c24ba71fd0969fa55634f getblockcount
|
||||
```
|
||||
|
||||
### Verificando Nossa Configuração do Tor para o Bitcoind
|
||||
|
||||
O Bitcoin Standup também garante que nosso ```bitcoind``` esteja configurado para se comunicar opcionalmente em um endereço onion.
|
||||
|
||||
Podemos verificar a configuração inicial do Tor para o ```bitcoind``` executando grep para "tor" no ```debug.log``` em nosso diretório de dados:
|
||||
```
|
||||
$ grep "tor:" ~/.bitcoin/testnet3/debug.log
|
||||
2021-06-09T14:07:04Z tor: ADD_ONION successful
|
||||
2021-06-09T14:07:04Z tor: Got service ID vazr3k6bgnfafmdpcmbegoe5ju5kqyz4tk7hhntgaqscam2qupdtk2yd, advertising service vazr3k6bgnfafmdpcmbegoe5ju5kqyz4tk7hhntgaqscam2qupdtk2yd.onion:18333
|
||||
2021-06-09T14:07:04Z tor: Cached service private key to /home/standup/.bitcoin/testnet3/onion_v3_private_key
|
||||
```
|
||||
> :information_source: **NOTA:** O Bitcoin Core não suporta mais endereços v2. O suporte ao Tor v2 foi removido no Pull Request [#22050](https://github.com/bitcoin/bitcoin/pull/22050)
|
||||
|
||||
> **TESTNET vs MAINNET:** Na Mainnet o ```bitcoind``` responde usando a porta 8333, na testnet, na porta 18333.
|
||||
|
||||
Podemos verificar se um serviço oculto Tor foi criado para o Bitcoin usando o comando RPC ```getnetworkinfo```:
|
||||
|
||||
```
|
||||
$ bitcoin-cli getnetworkinfo
|
||||
...
|
||||
"localaddresses": [
|
||||
{
|
||||
"address": "173.255.245.83",
|
||||
"port": 18333,
|
||||
"score": 1
|
||||
},
|
||||
{
|
||||
"address": "2600:3c01::f03c:92ff:fe86:f26",
|
||||
"port": 18333,
|
||||
"score": 1
|
||||
},
|
||||
{
|
||||
"address": "vazr3k6bgnfafmdpcmbegoe5ju5kqyz4tk7hhntgaqscam2qupdtk2yd.onion",
|
||||
"port": 18333,
|
||||
"score": 4
|
||||
}
|
||||
],
|
||||
...
|
||||
```
|
||||
Isso mostra três endereços para acessarmos nosso servidor Bitcoin, um endereço IPv4 (```173.255.245.83```), um endereço IPv6 (```2600:3c01::f03c:92ff:fe86:f26```), e um endereço Tor (```vazr3k6bgnfafmdpcmbegoe5ju5kqyz4tk7htgtgaq2qudsc```).
|
||||
|
||||
> :warning: **AVISO:** Obviamente, nunca podemos revelar seu endereço Tor de uma forma que esteja associada ao nosso nome ou a outras PII ("personably identifiable information", ou informações de identificação pessoal)!
|
||||
|
||||
Podemos ver algumas informações semelhantes com o ```getnetworkinfo```.
|
||||
```
|
||||
bitcoin-cli getnetworkinfo
|
||||
{
|
||||
"version": 200000,
|
||||
"subversion": "/Satoshi:0.20.0/",
|
||||
"protocolversion": 70015,
|
||||
"localservices": "0000000000000408",
|
||||
"localservicesnames": [
|
||||
"WITNESS",
|
||||
"NETWORK_LIMITED"
|
||||
],
|
||||
"localrelay": true,
|
||||
"timeoffset": 0,
|
||||
"networkactive": true,
|
||||
"connections": 10,
|
||||
"networks": [
|
||||
{
|
||||
"name": "ipv4",
|
||||
"limited": false,
|
||||
"reachable": true,
|
||||
"proxy": "",
|
||||
"proxy_randomize_credentials": false
|
||||
},
|
||||
{
|
||||
"name": "ipv6",
|
||||
"limited": false,
|
||||
"reachable": true,
|
||||
"proxy": "",
|
||||
"proxy_randomize_credentials": false
|
||||
},
|
||||
{
|
||||
"name": "onion",
|
||||
"limited": false,
|
||||
"reachable": true,
|
||||
"proxy": "127.0.0.1:9050",
|
||||
"proxy_randomize_credentials": true
|
||||
}
|
||||
],
|
||||
"relayfee": 0.00001000,
|
||||
"incrementalfee": 0.00001000,
|
||||
"localaddresses": [
|
||||
{
|
||||
"address": "173.255.245.83",
|
||||
"port": 18333,
|
||||
"score": 1
|
||||
},
|
||||
{
|
||||
"address": "2600:3c01::f03c:92ff:fe86:f26",
|
||||
"port": 18333,
|
||||
"score": 1
|
||||
},
|
||||
{
|
||||
"address": "vazr3k6bgnfafmdpcmbegoe5ju5kqyz4tk7hhntgaqscam2qupdtk2yd.onion",
|
||||
"port": 18333,
|
||||
"score": 4
|
||||
}
|
||||
],
|
||||
"warnings": ""
|
||||
}
|
||||
```
|
||||
Este serviço oculto permitirá conexões anônimas com o nosso ```bitcoind``` através da rede Bitcoin.
|
||||
|
||||
> :warning: **AVISO:** Executar o Tor e ter um serviço oculto do Tor não nos obriga a usar o Tor.
|
||||
|
||||
### Verificando Nossa Configuração do Tor para os Peers
|
||||
|
||||
Usando o comando RPC ```getpeerinfo```, podemos ver quais nodes estão conectados ao nosso node e verificar se eles estão conectados ao Tor.
|
||||
|
||||
```
|
||||
$ bitcoin-cli getpeerinfo
|
||||
```
|
||||
Alguns podem estar conectados via Tor:
|
||||
```
|
||||
...
|
||||
{
|
||||
"id": 9,
|
||||
"addr": "nkv.......xxx.onion:8333",
|
||||
"addrbind": "127.0.0.1:51716",
|
||||
"services": "000000000000040d",
|
||||
"servicesnames": [
|
||||
"NETWORK",
|
||||
"BLOOM",
|
||||
"WITNESS",
|
||||
"NETWORK_LIMITED"
|
||||
],
|
||||
"relaytxes": true,
|
||||
"lastsend": 1593981053,
|
||||
"lastrecv": 1593981057,
|
||||
"bytessent": 1748,
|
||||
"bytesrecv": 41376,
|
||||
"conntime": 1593980917,
|
||||
"timeoffset": -38,
|
||||
"pingwait": 81.649295,
|
||||
"version": 70015,
|
||||
"subver": "/Satoshi:0.20.0/",
|
||||
"inbound": false,
|
||||
"addnode": false,
|
||||
"startingheight": 637875,
|
||||
"banscore": 0,
|
||||
"synced_headers": -1,
|
||||
"synced_blocks": -1,
|
||||
"inflight": [
|
||||
],
|
||||
"whitelisted": false,
|
||||
"permissions": [
|
||||
],
|
||||
"minfeefilter": 0.00000000,
|
||||
"bytessent_per_msg": {
|
||||
"addr": 55,
|
||||
"feefilter": 32,
|
||||
"getaddr": 24,
|
||||
"getheaders": 1053,
|
||||
"inv": 280,
|
||||
"ping": 32,
|
||||
"pong": 32,
|
||||
"sendcmpct": 66,
|
||||
"sendheaders": 24,
|
||||
"verack": 24,
|
||||
"version": 126
|
||||
},
|
||||
"bytesrecv_per_msg": {
|
||||
"addr": 30082,
|
||||
"feefilter": 32,
|
||||
"getdata": 280,
|
||||
"getheaders": 1053,
|
||||
"headers": 106,
|
||||
"inv": 9519,
|
||||
"ping": 32,
|
||||
"pong": 32,
|
||||
"sendcmpct": 66,
|
||||
"sendheaders": 24,
|
||||
"verack": 24,
|
||||
"version": 126
|
||||
}
|
||||
}
|
||||
...
|
||||
```
|
||||
Alguns podem não estar, como esta conexão IPv6:
|
||||
```
|
||||
...
|
||||
{
|
||||
"id": 17,
|
||||
"addr": "[2001:638:a000:4140::ffff:191]:18333",
|
||||
"addrlocal": "[2600:3c01::f03c:92ff:fe86:f26]:36344",
|
||||
"addrbind": "[2600:3c01::f03c:92ff:fe86:f26]:36344",
|
||||
"services": "0000000000000409",
|
||||
"servicesnames": [
|
||||
"NETWORK",
|
||||
"WITNESS",
|
||||
"NETWORK_LIMITED"
|
||||
],
|
||||
"relaytxes": true,
|
||||
"lastsend": 1595447081,
|
||||
"lastrecv": 1595447067,
|
||||
"bytessent": 12250453,
|
||||
"bytesrecv": 2298711417,
|
||||
"conntime": 1594836414,
|
||||
"timeoffset": -1,
|
||||
"pingtime": 0.165518,
|
||||
"minping": 0.156638,
|
||||
"version": 70015,
|
||||
"subver": "/Satoshi:0.20.0/",
|
||||
"inbound": false,
|
||||
"addnode": false,
|
||||
"startingheight": 1780784,
|
||||
"banscore": 0,
|
||||
"synced_headers": 1781391,
|
||||
"synced_blocks": 1781391,
|
||||
"inflight": [
|
||||
],
|
||||
"whitelisted": false,
|
||||
"permissions": [
|
||||
],
|
||||
"minfeefilter": 0.00001000,
|
||||
"bytessent_per_msg": {
|
||||
"addr": 4760,
|
||||
"feefilter": 32,
|
||||
"getaddr": 24,
|
||||
"getdata": 8151183,
|
||||
"getheaders": 1085,
|
||||
"headers": 62858,
|
||||
"inv": 3559475,
|
||||
"ping": 162816,
|
||||
"pong": 162816,
|
||||
"sendcmpct": 132,
|
||||
"sendheaders": 24,
|
||||
"tx": 145098,
|
||||
"verack": 24,
|
||||
"version": 126
|
||||
},
|
||||
"bytesrecv_per_msg": {
|
||||
"addr": 33877,
|
||||
"block": 2291124374,
|
||||
"feefilter": 32,
|
||||
"getdata": 9430,
|
||||
"getheaders": 1085,
|
||||
"headers": 60950,
|
||||
"inv": 2019175,
|
||||
"ping": 162816,
|
||||
"pong": 162816,
|
||||
"sendcmpct": 66,
|
||||
"sendheaders": 24,
|
||||
"tx": 5136622,
|
||||
"verack": 24,
|
||||
"version": 126
|
||||
}
|
||||
}
|
||||
...
|
||||
```
|
||||
Ter um endereço Tor para nosso ```bitcoind``` é provavelmente um pouco menos útil do que ter um endereço Tor para nossas conexões RPC. Isso é verdade porque não é recomendado tentar enviar todas as nossas conexões Bitcoin via Tor, e em parte porque proteger nossos comandos RPC é o que realmente importa. É muito mais provável que façamos isso remotamente, a partir de uma carteira de software como a Gordian Wallet, enquanto o nosso próprio servidor tem mais probabilidade de estar no escritório, no porão ou em um bunker.
|
||||
|
||||
No entanto, existem maneiras de fazer o ```bitcoind``` usar mais o Tor, conforme iremos discutir na próxima seção.
|
||||
|
||||
## Resumo: Verificando Nossa Configuração do Tor
|
||||
|
||||
O Tor é um pacote de software instalado como parte do Bitcoin Standup que permite a troca de comunicações anonimamente. Ele protegerá nossas portas RPC (8332 ou 18332) e nossas portas do ```bitcoind``` (8333 ou 18333), porém, teremos que nos conectar ativamente ao endereço onion para utilizá-las! O Tor é um pilar fundamental da privacidade e segurança para a nossa configuração do Bitcoin, e podemos verificar se ele está disponível e vinculado ao Bitcoin com alguns comandos simples.
|
||||
|
||||
> :fire: ***Qual é o poder do Tor?*** Muitos ataques a usuários de Bitcoin dependem da informação de quem é a vítima e que ela possui Bitcoins. O Tor pode nos proteger disso, escondendo onde estamos e o que estamos fazendo. É particularmente importante se desejamos nos conectar ao nosso próprio node remotamente por meio de uma carteira de software, e pode ser crucial se fizermos isso em algum país onde o uso de Bitcoin é mal visto. Se precisarmos acessar nossos serviços Bitcoin remotamente, precisamos nos certificar de que nossa carteira seja totalmente compatível com o Tor e envie todos os comandos RPC ao nosso servidor usando esse protocolo.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos continuar "Usando o Tor" na seção [§14.2: Mudando Nossos Serviços Ocultos do Bitcoin](14_2_Changing_Your_Bitcoin_Hidden_Services.md).
|
74
pt/14_2_Changing_Your_Bitcoin_Hidden_Services.md
Normal file
74
pt/14_2_Changing_Your_Bitcoin_Hidden_Services.md
Normal file
@ -0,0 +1,74 @@
|
||||
# 14.2: Mudando Nossos Serviços Ocultos do Bitcoin
|
||||
|
||||
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
|
||||
|
||||
Temos um serviço Tor funcionando, mas com o tempo talvez queiramos reiniciá-lo ou ajustá-lo de outra forma.
|
||||
|
||||
## Protejendo Nossos Serviços Ocultos
|
||||
|
||||
O Tor permite que limitemos quais clientes conversam com nossos serviços ocultos. Se ainda não autorizamos nosso cliente durante a configuração do servidor, na primeira oportunidade devemos fazer o seguinte:
|
||||
|
||||
1. Solicitar uma chave pública de autenticação Tor V3 do nosso cliente. (Na [GordianWallet](https://github.com/BlockchainCommons/GordianWallet-iOS), está disponível no menu de configurações).
|
||||
2. Vamos para o subdiretório apropriado para nosso serviço oculto do Bitcoin. Se usamos o Bitcoin Standup é ```/var/lib/tor/standup/```.
|
||||
3. Vamos para o subdiretório ```authorized_clients```.
|
||||
4. Vamos adicionar um arquivo chamado ```[qualquer coisa].auth```. O ```[qualquer coisa]``` pode ser realmente qualquer coisa.
|
||||
5. Colocamos a chave pública (e nada mais) no arquivo.
|
||||
|
||||
Depois de adicionar um arquivo ```.auth``` ao subdiretório ```authorized_client```, somente os clientes autorizados serão capazes de se comunicar com esse serviço oculto. Podemos adicionar mais ou menos 330 chaves públicas diferentes para habilitar clientes diferentes.
|
||||
|
||||
## Redefinindo Nosso Endereço Onion do ```bitcoind```
|
||||
|
||||
Se quisermos redefinir nosso endereço onion para o ```bitcoind```, podemos apenas remover o ```onion_private_key``` do nosso diretório de dados, no `~/.bitcoin/testnet`:
|
||||
```
|
||||
$ cd ~/.bitcoin/testnet
|
||||
$ rm onion_private_key
|
||||
```
|
||||
Quando reiniciarmos, um novo endereço onion será gerado:
|
||||
```
|
||||
2020-07-22T23:52:27Z tor: Got service ID pyrtqyiqbwb3rhe7, advertising service pyrtqyiqbwb3rhe7.onion:18333
|
||||
2020-07-22T23:52:27Z tor: Cached service private key to /home/standup/.bitcoin/testnet3/onion_private_key
|
||||
```
|
||||
|
||||
## Redefinindo Nosso Endereço Onion do RPC
|
||||
|
||||
Se quisermos redefinir nosso endereço onion para o acesso RPC, podemos excluir da mesma forma o ```HiddenServiceDirectory``` apropriado e reiniciar o Tor:
|
||||
```
|
||||
$ sudo rm -rf /var/lib/tor/standup/
|
||||
$ sudo /etc/init.d/tor restart
|
||||
```
|
||||
|
||||
> :warning: **AVISO:** Redefinir o endereço onion do RPC desconectará quaisquer carteiras mobile ou outros serviços que contamos usando a API Quicklink. Por isso, temos que tomar bastante cuidado.
|
||||
|
||||
## Forçando o ```bitcoind``` a Usar o Tor
|
||||
|
||||
Finalmente, podemos forçar o ```bitcoind``` a usar o onion adicionando o seguinte ao nosso arquivo ```bitcoin.conf```:
|
||||
```
|
||||
proxy=127.0.0.1:9050
|
||||
listen=1
|
||||
bind=127.0.0.1
|
||||
onlynet=onion
|
||||
```
|
||||
Precisaremos adicionar seed nodes baseados no onion ou outros nodes à nossa configuração, mais uma vez editando o ```bitcoin.conf```:
|
||||
```
|
||||
seednode=address.onion
|
||||
seednode=address.onion
|
||||
seednode=address.onion
|
||||
seednode=address.onion
|
||||
addnode=address.onion
|
||||
addnode=address.onion
|
||||
addnode=address.onion
|
||||
addnode=address.onion
|
||||
```
|
||||
Depois, basta reiniciar o ```tor``` e o ```bitcoind```.
|
||||
|
||||
Agora devemos estar nos comunicando exclusivamente com o Tor. Mas, a menos que estejamos em um local hostil, esse nível de anonimato provavelmente não é necessário. Também não é particularmente recomendado, pois podemos diminuir muito o número de potenciais peers, criando problemas de censura ou mesmo de correlação. Também podemos começar a sofrer com alta latência. E essa configuração pode nos dar uma falsa sensação de anonimato que realmente não existe na rede Bitcoin.
|
||||
|
||||
> :warning: **AVISO:** Esta configuração não foi testada! Use por sua conta e risco!
|
||||
|
||||
## Resumo: Mudando Nossos Serviços Ocultos do Bitcoin
|
||||
|
||||
Provavelmente nós não precisaremos brincar com os nossos serviços onion depois de verificá-los, mas caso precisemos, aqui está como redefinir um endereço Tor que foi comprometido ou passar a usar exclusivamente o Tor com nosso ```bitcoind``` .
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos continuar "Usando o Tor" na seção [14.3: Adicionando Serviços SSH Ocultos](14_3_Adding_SSH_Hidden_Services.md).
|
59
pt/14_3_Adding_SSH_Hidden_Services.md
Normal file
59
pt/14_3_Adding_SSH_Hidden_Services.md
Normal file
@ -0,0 +1,59 @@
|
||||
# 14.3: Adicionando um Serviço SSH Oculto
|
||||
|
||||
>:information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
|
||||
|
||||
Até agora, usamos o Tor com os nossos serviços Bitcoin, mas também podemos usá-lo para proteger outros serviços em nossa máquina, melhorando a segurança e a privacidade. Esta seção demonstra como fazer isso, introduzindo um serviço ```ssh``` oculto para fazer o login remotamente usando o Tor.
|
||||
|
||||
## Criando serviços SSH ocultos
|
||||
|
||||
Novos serviços são criados adicionando-os ao arquivo ```/etc/tor/torrc```:
|
||||
```
|
||||
$ su
|
||||
# cat >> /etc/tor/torrc << EOF
|
||||
HiddenServiceDir /var/lib/tor/hidden-service-ssh/
|
||||
HiddenServicePort 22 127.0.0.1:22
|
||||
EOF
|
||||
# exit
|
||||
```
|
||||
Eis o que cada coisa significa:
|
||||
|
||||
* HiddenServiceDir: Indica que temos um diretório de serviço oculto com a configuração necessária para este caminho.
|
||||
* HiddenServicePort: Indica a porta Tor a ser usada; no caso do SSH, geralmente é a 22.
|
||||
|
||||
Depois de adicionar as linhas apropriadas ao nosso arquivo ```torrc```, precisaremos reiniciar o Tor:
|
||||
```
|
||||
$ sudo /etc/init.d/tor restart
|
||||
```
|
||||
|
||||
Após a reinicialização, nosso ```HiddenServiceDir``` deve ter novos arquivos da seguinte forma:
|
||||
```
|
||||
$ sudo ls -l /var/lib/tor/hidden-service-ssh
|
||||
total 16
|
||||
drwx--S--- 2 debian-tor debian-tor 4096 Jul 22 14:55 authorized_clients
|
||||
-rw------- 1 debian-tor debian-tor 63 Jul 22 14:56 hostname
|
||||
-rw------- 1 debian-tor debian-tor 64 Jul 22 14:55 hs_ed25519_public_key
|
||||
-rw------- 1 debian-tor debian-tor 96 Jul 22 14:55 hs_ed25519_secret_key
|
||||
```
|
||||
O arquivo ```hostname``` neste diretório contém nosso novo ID onion:
|
||||
```
|
||||
$ sudo cat /var/lib/tor/hidden-service-ssh/hostname
|
||||
qwkemc3vusd73glx22t3sglf7izs75hqodxsgjqgqlujemv73j73qpid.onion
|
||||
```
|
||||
Podemos nos conectar ao serviço oculto ```ssh``` usando o ```torify``` e esse endereço:
|
||||
```
|
||||
$ torify ssh standup@qwkemc3vusd73glx22t3sglf7izs75hqodxsgjqgqlujemv73j73qpid.onion
|
||||
The authenticity of host 'qwkemc3vusd73glx22t3sglf7izs75hqodxsgjqgqlujemv73j73qpid.onion (127.42.42.0)' can't be established.
|
||||
ECDSA key fingerprint is SHA256:LQiWMtM8qD4Nv7eYT1XwBPDq8fztQafEJ5nfpNdDtCU.
|
||||
Are you sure you want to continue connecting (yes/no)? yes
|
||||
Warning: Permanently added 'qwkemc3vusd73glx22t3sglf7izs75hqodxsgjqgqlujemv73j73qpid.onion' (ECDSA) to the list of known hosts.
|
||||
standup@qwkemc3vusd73glx22t3sglf7izs75hqodxsgjqgqlujemv73j73qpid.onion's password:
|
||||
```
|
||||
## Resumo: Adicionando um Serviço SSH Oculto
|
||||
|
||||
Agora que instalamos o Tor e sabemos como usá-lo, podemos adicionar outros serviços ao Tor. Apenas adicionamos as linhas ao nosso ```torrc``` (no nosso servidor) e o conectamos com o ```torify``` (no nosso cliente).
|
||||
|
||||
> :fire: ***Qual é o poder de utilizar outros serviços ocultos?*** Cada vez que acessamos um serviço em nosso servidor remotamente, deixamos pegadas na rede. Mesmo que os dados sejam criptografados usando SSH (ou TLS), os vigias da rede podem ver de onde estamos nos conectando, para onde estamos conectando e qual serviço estamos usando. Isso realmente importa pra nós? Esta é a pergunta que devemos fazer. Mas se a resposta for "Sim", podemos proteger a conexão com um serviço oculto.
|
||||
|
||||
Vamos seguir "Programando com o RPC" no [Capítulo Dezesseis: Conversando com o Bitcoind usando C](16_0_Talking_to_Bitcoind.md).
|
||||
|
||||
Ou, se você não for um programador, pode pular para o [Capítulo Dezenove: Entendendo Nossa Configuração da Lightning](19_0_Understanding_Your_Lightning_Setup.md) para aumentar nosso conhecimento sobre a Lightning Network usando a linha de comando.
|
27
pt/16_0_Talking_to_Bitcoind.md
Normal file
27
pt/16_0_Talking_to_Bitcoind.md
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
# Capítulo 15: Conversando com Bitcoind usando C
|
||||
|
||||
Enquanto trabalhamos com Bitcoin Scripts, atingimos os limites do que era possível com o `bitcoin-cli`: Atualmente, ele não pode ser usado para gerar transações contendo scripts incomuns. Os scripts shell também não são bons para algumas coisas, como criar programas de escuta que estão constantemente em polling. Felizmente, existem outras maneiras de acessar a rede Bitcoin: Através de APIs programáveis.
|
||||
|
||||
Esta seção se concentra em três diferentes bibliotecas que podem ser usadas como base de programação C sofisticada: Uma biblioteca RPC e uma biblioteca JSON que juntas permitem recriar muito do que fazemos nos scripts de shell, porém, usando C; enquanto uma biblioteca ZMQ nos conecta a notificações, algo que não conseguiríamos acessar até agora. (O próximo capítulo cobrirá uma biblioteca ainda mais sofisticada chamada Libwally, para finalizar esta introdução à programação do Bitcoin com C).
|
||||
|
||||
## Objetivos deste capítulo
|
||||
|
||||
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
|
||||
|
||||
* Criar programas C que usam RPC para conversar com o Bitcoind;
|
||||
* Criar programas C que usam ZMQ para conversar com o Bitcoind.
|
||||
|
||||
Os objetivos secundários do capítulo incluem a capacidade de:
|
||||
|
||||
* Entender como usar uma biblioteca RPC;
|
||||
* Entender como usar uma biblioteca JSON;
|
||||
* Compreender as capacidades do ZMQ;
|
||||
* Entender como usar uma biblioteca ZMQ.
|
||||
|
||||
## Tabela de conteúdo
|
||||
|
||||
* [Seção 1: Acessando o Bitcoind usando C com Bibliotecas RPC](15_1_Accessing_Bitcoind_with_C.md)
|
||||
* [Seção 2: Programando o Bitcoind usando C com Bibliotecas RPC](15_2_Programming_Bitcoind_with_C.md)
|
||||
* [Seção 3: Recebendo notificações usando C com bibliotecas ZMQ](15_3_Receiving_Bitcoind_Notifications_with_C.md)
|
||||
|
294
pt/16_1_Accessing_Bitcoind_with_C.md
Normal file
294
pt/16_1_Accessing_Bitcoind_with_C.md
Normal file
@ -0,0 +1,294 @@
|
||||
|
||||
# 15.1: Acessando o Bitcoind usando C com bibliotecas RPC
|
||||
|
||||
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um esboço que ainda pode estar aguardando revisão. Portanto, leitor, tenha cuidado.
|
||||
|
||||
Você já viu uma maneira alternativa de acessar as portas RPC do Bitcoind: Usando o ``curl``, que cobrimos no [Capítulo 4 Prefácio](04_4__interlude_using_curl.md). Interagir com o ``Bitcoind`` através de uma biblioteca de RPC usando C não é diferente do que já vimos, só precisamos de boas bibliotecas para nos auxiliar. Esta seção introduz um pacote chamado ``libbitcoinrpc``, que permite acessar a porta JSON-RPC do ``bitcoind``. Ele usa uma biblioteca ``curl`` para acessar os dados e usa a biblioteca ``jansson`` para codificar e decodificar o JSON.
|
||||
|
||||
## Configurando o libbitcoinrpc
|
||||
|
||||
Para usar o ``libbitcoinrpc``, precisaremos instalar uma configuração básica C e os pacotes dependentes, que são ``libcurl``, ``libjansson``, e ``libuuid``. Depois faremos isso no seu servidor Standup Bitcoin (ou em qualquer outro servidor Ubuntu).
|
||||
|
||||
```
|
||||
$ sudo apt-get install make gcc libcurl4-openssl-dev libjansson-dev uuid-dev
|
||||
Suggested packages:
|
||||
libcurl4-doc libidn11-dev libkrb5-dev libldap2-dev librtmp-dev libssh2-1-dev
|
||||
The following NEW packages will be installed:
|
||||
libcurl4-openssl-dev libjansson-dev uuid-dev
|
||||
0 upgraded, 3 newly installed, 0 to remove and 4 not upgraded.
|
||||
Need to get 358 kB of archives.
|
||||
After this operation, 1.696 kB of additional disk space will be used.
|
||||
Do you want to continue? [Y/n] y
|
||||
```
|
||||
Agora, podemos baixar o [libbitcoinrpc no github](https://github.com/gitmarek/libbitcoinrpc/blob/master/readme.md). Vamos clonar ou pegar um arquivo zip, do jeito que preferir.
|
||||
|
||||
```
|
||||
$ sudo apt-get install git
|
||||
$ git clone https://github.com/gitmarek/libbitcoinrpc
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO** Uma alteração no RPC "signrawtransaction" causou uma assinatura com ``libbitcoinrpc`` para o segfault no Bitcoin 0.17 ou superior. O [Pull Request foi submetido](https://github.com/gitmarek/libbitcoinrpc/pull/1/commits) para resolver o problema, mas se ainda não tiver sido feito o merge, podemos simplesmente fazer uma simples mudança no código-fonte para ``src/bitcoinrpc_method.c`` antes de compilarmos.
|
||||
|
||||
### Compilando o libbitcoinrpc.
|
||||
|
||||
Antes de compilarmos e instalarmos o pacote, provavelmente precisaremos ajustar nosso ``$PATH``, para que possamos acessar o ``/sbin/ldconfig``:
|
||||
```
|
||||
$ PATH="/sbin:$PATH"
|
||||
```
|
||||
|
||||
Para o Ubuntu, também precisaremos ajustar o ``install_libpath`` no ``makefile`` do ``libbitcoinrpc`` para instalar no ``/usr/lib`` ao invés do ``/usr/local/lib``:
|
||||
|
||||
```
|
||||
$ emacs ~/libbitcoinrpc/Makefile
|
||||
...
|
||||
INSTALL_LIBPATH := $(INSTALL_PREFIX)/usr/lib
|
||||
```
|
||||
|
||||
(Se preferir não usar o ``/usr/lib``, precisará alterar o ``etc/ld.so.conf`` ou os arquivos dependentes de maneira apropriada... Porém, para uma configuração de teste em uma máquina de teste, acredito que isso não seja um problema).
|
||||
|
||||
Da mesma forma, vamos precisar ajustar o ``install_headerpath`` no ``Makefile`` do ``libbitcoinrpc`` para instalar no caminho ``/usr/include`` ao invés do ``/usr/local/inclusve``:
|
||||
|
||||
```
|
||||
...
|
||||
INSTALL_HEADERPATH := $(INSTALL_PREFIX)/usr/include
|
||||
```
|
||||
|
||||
Agora, podemos compilar:
|
||||
```
|
||||
$ cd libbitcoinrpc
|
||||
~/libbitcoinrpc$ make
|
||||
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_err.o -c src/bitcoinrpc_err.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_global.o -c src/bitcoinrpc_global.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc.o -c src/bitcoinrpc.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_resp.o -c src/bitcoinrpc_resp.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_cl.o -c src/bitcoinrpc_cl.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_method.o -c src/bitcoinrpc_method.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -shared -Wl,-soname,libbitcoinrpc.so.0 \
|
||||
src/bitcoinrpc_err.o src/bitcoinrpc_global.o src/bitcoinrpc.o src/bitcoinrpc_resp.o src/bitcoinrpc_cl.o src/bitcoinrpc_method.o \
|
||||
-o .lib/libbitcoinrpc.so.0.2 \
|
||||
-Wl,--copy-dt-needed-entries -luuid -ljansson -lcurl
|
||||
ldconfig -v -n .lib
|
||||
.lib:
|
||||
libbitcoinrpc.so.0 -> libbitcoinrpc.so.0.2 (changed)
|
||||
ln -fs libbitcoinrpc.so.0 .lib/libbitcoinrpc.so
|
||||
```
|
||||
Se tudo correr bem, podemos instalar o pacote:
|
||||
```
|
||||
$ sudo make install
|
||||
Installing to
|
||||
install .lib/libbitcoinrpc.so.0.2 /usr/local/lib
|
||||
ldconfig -n /usr/local/lib
|
||||
ln -fs libbitcoinrpc.so.0 /usr/local/lib/libbitcoinrpc.so
|
||||
install -m 644 src/bitcoinrpc.h /usr/local/include
|
||||
Installing docs to /usr/share/doc/bitcoinrpc
|
||||
mkdir -p /usr/share/doc/bitcoinrpc
|
||||
install -m 644 doc/*.md /usr/share/doc/bitcoinrpc
|
||||
install -m 644 CREDITS /usr/share/doc/bitcoinrpc
|
||||
install -m 644 LICENSE /usr/share/doc/bitcoinrpc
|
||||
install -m 644 Changelog.md /usr/share/doc/bitcoinrpc
|
||||
Installing man pages
|
||||
install -m 644 doc/man3/bitcoinrpc*.gz /usr/local/man/man3
|
||||
```
|
||||
|
||||
## Preparando o código
|
||||
|
||||
``libbitcoinrpc`` tem métodos simples e bem estruturados para conectar-se ao nosso `bitcoind`, executando chamadas RPC e decodificando a resposta.
|
||||
|
||||
Para usar o ``libbitcoinrpc``, é importante certificar de que nossos arquivos do código incluam os cabeçalhos apropriados:
|
||||
``` c
|
||||
#include <jansson.h>
|
||||
#include <bitcoinrpc.h>
|
||||
```
|
||||
|
||||
Precisaremos também vincular as bibliotecas apropriadas sempre que possamos compilar:
|
||||
|
||||
```
|
||||
$ cc yourcode.c -lbitcoinrpc -ljansson -o yourcode
|
||||
```
|
||||
|
||||
## Construindo a conexão
|
||||
|
||||
Para construir a conexão com o servidor ``bitcoind`` é necessário alguns simples passos.
|
||||
|
||||
Primeiro, inicialize a biblioteca:
|
||||
```
|
||||
bitcoinrpc_global_init();
|
||||
```
|
||||
Em seguida, vamos conectar ao ``Bitcoind`` com ``bitcoinrpc_cl_init_params``. Os quatro argumentos necessários para o ``bitcoinrpc_cl_init_params`` são o nome de usuário, a senha, o endereço IP e a porta. A esta altura, você deve saber todas essas informações, já que foram necessárias para realizar o trabalho com o [curl](04_4__interlude_using_curl.md). Apenas para recordar, o endereço de IP é 127.0.0.1 e a porta 18332 devem estar corretos para a configuração padrão da testenet descrita neste documento, enquanto podemos encontrar o usuário e a senha no arquivo ``~/.bitcoin/bitcoin.conf``.
|
||||
```
|
||||
$ cat bitcoin.conf
|
||||
server=1
|
||||
dbcache=1536
|
||||
par=1
|
||||
maxuploadtarget=137
|
||||
maxconnections=16
|
||||
rpcuser=StandUp
|
||||
rpcpassword=6305f1b2dbb3bc5a16cd0f4aac7e1eba
|
||||
rpcallowip=127.0.0.1
|
||||
debug=tor
|
||||
prune=550
|
||||
testnet=1
|
||||
[test]
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=18332
|
||||
[main]
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=8332
|
||||
[regtest]
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=18443
|
||||
```
|
||||
Com essas informações, vamos colocá-las no ``bitcoinrpc_cl_init_params``:
|
||||
``` c
|
||||
bitcoinrpc_cl_t *rpc_client;
|
||||
rpc_client = bitcoinrpc_cl_init_params("StandUp", "6305f1b2dbb3bc5a16cd0f4aac7e1eba", "127.0.0.1", 18332);
|
||||
```
|
||||
|
||||
> **MAINNET VS TESTNET:** A porta seria a 8332 caso estivéssemos usando a configuração da rede principal.
|
||||
|
||||
Se o ``rpc_client`` for inicializado com sucesso, poderemos enviar os comandos do RPC.
|
||||
|
||||
Mais tarde, quando tivermos feito com a conexão de ``bitcoind``, poderemos fechar da seguinte maneira:
|
||||
``` c
|
||||
bitcoinrpc_global_cleanup();
|
||||
```
|
||||
|
||||
### Testando o código de teste
|
||||
|
||||
O código de teste pode ser encontrado [no diretório src com o nome 15_1_testbitcoin.c](src/15_1_testbitcoin.c). Vamos fazer o download para a nossa máquina TestNet e depois inserir a senha correta do RPC (e alterar o usuário RPC se não tivermos criado o servidor com StandUp).
|
||||
|
||||
Podemos compilar e executar o código da seguinte maneira:
|
||||
```
|
||||
$ cc testbitcoin.c -lbitcoinrpc -ljansson -o testbitcoin
|
||||
$ ./testbitcoin
|
||||
Successfully connected to server!
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** Se esquecermos de inserir a senha RPC nesta ou em qualquer outro código que possuem dependências do RPC, receberemos um misterioso ``ERROR CODE 5``.
|
||||
|
||||
## Fazendo uma chamada ao RPC
|
||||
|
||||
Para usarmos um método RPC usando ``libbitcoinrpc``, devemos inicializar uma variável do tipo ``bitcoinrpc_method_t``. Podemos fazer com o valor apropriado para o método que desejamos utilizar, que estão todos listados na [Referências do BitcoinRPC](https://github.com/gitmarek/libbitcoinrpc/blob/master/doc/reference.md).
|
||||
``` c
|
||||
bitcoinrpc_method_t *getmininginfo = NULL;
|
||||
getmininginfo = bitcoinrpc_method_init(BITCOINRPC_METHOD_GETMININGINFO);
|
||||
```
|
||||
Normalmente definiríamos os parâmetros em seguida, mas o ``GetMiningInfo`` não requer parâmetros, por isso podemos pular essa parte.
|
||||
|
||||
Também devemos criar outros dois objetos, um "objeto de resposta" e um "objeto de erro". Eles podem ser inicializados da seguinte forma:
|
||||
``` c
|
||||
bitcoinrpc_resp_t *btcresponse = NULL;
|
||||
btcresponse = bitcoinrpc_resp_init();
|
||||
|
||||
bitcoinrpc_err_t btcerror;
|
||||
```
|
||||
Vamos usar a variável ``rpc_client`` que aprendemos no teste anterior e vamos adicionar nosso método ``getmininginfo`` e os outros dois objetos:
|
||||
``` c
|
||||
bitcoinrpc_call(rpc_client, getmininginfo, btcresponse, &btcerror);
|
||||
```
|
||||
|
||||
### Mostrando o retorno da chamada
|
||||
|
||||
Com certeza iremos querer saber o que a RPC retornou. Para fazermos isso, vamos recuperar a saída da nossa chamada como sendo um objeto JSON com ``bitcoinrpc_resp_get`` e vamos salvá-la em um objeto padrão ``jansson``, do tipo ``json_t``:
|
||||
``` c
|
||||
json_t *jsonresponse = NULL;
|
||||
jsonresponse = bitcoinrpc_resp_get(btcresponse);
|
||||
```
|
||||
Se quisermos gerar os resultados completos da chamada RPC no JSON, podemos fazer com uma simples invocação do ``json_dumps``, da biblioteca ``jansson``:
|
||||
``` c
|
||||
printf("%s\n", json_dumps(j, JSON_INDENT(2)));
|
||||
```
|
||||
No entanto, como agora estamos escrevendo programas completos, provavelmente iremos querer fazer um trabalho mais sutil, como retirar valores individuais do JSON para algum uso específico. A [Referência do Jansson](https6//jansson.readthedocs.Io/en/2.10/apiref.html) traz detalhes de como fazer.
|
||||
|
||||
Assim como estávamos usando o [curl](04_4__interlude_using_curl.md), descobrimos que o RPC retorna um objeto JSON contendo um ``ID``, um ``error`` e, mais importante, um objeto JSON do tipo ``result``.
|
||||
|
||||
A função ``json_object_get`` permite recuperar um valor (como o ``result``) de um objeto JSON usando chaves:
|
||||
``` c
|
||||
json_t *jsonresult = NULL;
|
||||
jsonresult = json_object_get(jsonresponse,"result");
|
||||
printf("%s\n", json_dumps(jsonresult, JSON_INDENT(2)));
|
||||
```
|
||||
|
||||
No entanto, provavelmente iremos querer analisar informações ainda mais profundas, para obter uma variável específica. Depois de recuperar o valor apropriado, precisaremos convertê-lo em um objeto C padrão usando a função ``JSON_*_value``. Por exemplo, para acessar um integer usamos o ``json_integer_value``:
|
||||
``` c
|
||||
json_t *jsonblocks = NULL;
|
||||
jsonblocks = json_object_get(jsonresult,"blocks");
|
||||
|
||||
int blocks;
|
||||
blocks = json_integer_value(jsonblocks);
|
||||
printf("Block Count: %d\n",blocks);
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** É extremamente fácil ocasionar erros de segmentação no código C quando estivermos trabalhando com os objetos ``jansson`` caso fiquemos confusos com que tipo de objeto estamos recuperando. Por isso, precisamos fazer isso com cuidado usando o ``bitcoin-cli help`` para saber o que devemos esperar, e se tivermos uma falha de segmentação, primeiro precisamos analisar se nossas funções de recuperação JSON estão corretas.
|
||||
|
||||
### Testando o código de informação
|
||||
|
||||
Vamos recuperar o código de teste que está no [diretório src](15_1_GetMiningInfo.c).
|
||||
```
|
||||
$ cc getmininginfo.c -lbitcoinrpc -ljansson -o getmininginfo
|
||||
$ ./getmininginfo
|
||||
Full Response: {
|
||||
"result": {
|
||||
"blocks": 1804406,
|
||||
"difficulty": 4194304,
|
||||
"networkhashps": 54842097951591.781,
|
||||
"pooledtx": 127,
|
||||
"chain": "test",
|
||||
"warnings": "Warning: unknown new rules activated (versionbit 28)"
|
||||
},
|
||||
"error": null,
|
||||
"id": "474ccddd-ef8c-4e3f-93f7-fde72fc08154"
|
||||
}
|
||||
|
||||
Just the Result: {
|
||||
"blocks": 1804406,
|
||||
"difficulty": 4194304,
|
||||
"networkhashps": 54842097951591.781,
|
||||
"pooledtx": 127,
|
||||
"chain": "test",
|
||||
"warnings": "Warning: unknown new rules activated (versionbit 28)"
|
||||
}
|
||||
|
||||
Block Count: 1804406
|
||||
```
|
||||
|
||||
## Fazendo uma chamada RPC usando argumentos
|
||||
|
||||
Mas e se a sua chamada RPC tiver argumentos?
|
||||
|
||||
### Criando uma matriz JSON
|
||||
|
||||
Para enviar parâmetros para a nossa chamada RPC usando ``libbitcoinrpc`` teremos que envolvê-los em uma matriz json. Como uma matriz é apenas uma simples listagem de valores, tudo o que precisamos fazer é codificar os parâmetros como elementos ordenados na matriz.
|
||||
|
||||
Vamos criar a matriz JSON usando a função ``json_array do`` do ``jansson``:
|
||||
``` c
|
||||
json_t *params = NULL;
|
||||
params = json_array();
|
||||
```
|
||||
Vamos fazer o processo inverso que fizemos para acessar valores do JSON: Vamos converter objetos no C para objetos no JSON usando as funções ``JSON_*``. Depois, vamos anexar tudo à matriz:
|
||||
``` c
|
||||
json_array_append_new(params,json_string(tx_rawhex));
|
||||
```
|
||||
|
||||
Observe que existem duas variantes para o comando de anexação: ``json_array_apend_new``, que acrescenta uma variável recém-criada, e ``json_array_apend``, que anexa uma variável existente.
|
||||
|
||||
Esta metodologia simples ``json_array_apend_new`` servirá para a maioria dos comandos RPC com parâmetros, mas alguns dos comandos RPC exigem entradas mais complexas. Nesses casos, precisaremos criar objetos JSON ou arrays em JSON, que anexaremos ao parâmetros de array como de costume. A próxima seção contém um exemplo de como fazer isso usando o ``CrayAwTransaction``, que contém uma matriz JSON de objetos JSON para as entradas, um objeto JSON para as saídas e o parâmetro ``locktime``.
|
||||
|
||||
### Atribuindo os parâmetros
|
||||
|
||||
Quando criamos o parâmetro array no JSON, simplesmente o atribuímos depois de inicializar o método RPC, da seguinte maneira:
|
||||
``` c
|
||||
bitcoinrpc_method_set_params(rpc_method, params)
|
||||
```
|
||||
Esta seção não inclui uma amostra abrangente dessa metodologia mais complexa, mas vamos vê-la em ação várias vezes no nosso primeiro programa C mais abrangente usando o RPC, na próxima seção.
|
||||
|
||||
## Resumo do capítulo Acessando o Bitcoind usando C com bibliotecas RPC
|
||||
|
||||
Ao vincular às bibliotecas ``BitcoinRPC`` do RPC e as bibliotecas ``jansson`` do JSON, podemos acessar facilmente o ``bitcoind`` usando chamadas RPC de uma biblioteca C. Para fazer isso, criamos uma conexão RPC, que faz as chamadas individuais de RPC, algumas delas passando alguns parâmetros. O ``jansson`` permite decodificar as respostas no formato JSON. A próxima seção demonstrará como isso pode ser usado para um programa de uso do mundo real.
|
||||
|
||||
* :fire: ***Qual é o poder de C?*** O C permite que façamos o próximo passo muito além do script shell, permitindo a criação de programas mais complexos e robustos.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos falar mais um pouco no "Conversando com o Bitcoind usando C" no capítulo [15.2: Programando o Bitcoind usando C com bibliotecas RPC](15_2_Programming_bitcoind_with_c.md).
|
354
pt/16_2_Programming_Bitcoind_with_C.md
Normal file
354
pt/16_2_Programming_Bitcoind_with_C.md
Normal file
@ -0,0 +1,354 @@
|
||||
|
||||
# 15.2: Programando o Bitcoind usando C com bibliotecas RPC
|
||||
|
||||
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho que pode estar aguardando revisão. Portanto, leitor, tenha cuidado.
|
||||
|
||||
A sessão [§15.1](15_1_Accessing_Bitcoind_with_C.md) apresentou a metodologia para a criação de programas C usando bibliotecas RPC e JSON. Agora vamos mostrar o potencial dessas bibliotecas C fazendo algumas coisas um pouco mais avançadas usando o programa real do Bitcoin.
|
||||
|
||||
## Planejando o código
|
||||
|
||||
Esta seção irá criar uma versão simples do ``sendtoaddress``, permitindo ao usuário enviar as moedas para um endereço, desde que tenha um UTXO grande o suficiente para isso. Aqui está o que precisamos fazer:
|
||||
|
||||
1. Solicitar um endereço e uma quantia;
|
||||
2. Definir uma taxa arbitrária;
|
||||
3. Preparar nosso RPC;
|
||||
4. Encontrar um UTXO que seja grande o suficiente para pagar o valor + a taxa;
|
||||
5. Criar uma mudança de endereço;
|
||||
6. Criar uma transação bruta que envie o UTXO para o endereço e altere o endereço;
|
||||
7. Assinar a transação;
|
||||
8. Enviar a transação.
|
||||
|
||||
### Planejando para o futuro
|
||||
|
||||
Como este é o nosso primeiro programa C funcional, vamos mantê-lo simples (ou seja, vamos usar a filosofia, _Keep it Simple_ ou também conhecida como KISS). Se estivéssemos produzindo um programa para estar em produção, desejaríamos pelo menos os seguintes passos:
|
||||
|
||||
1. Testar e/ou higienizar as entradas;
|
||||
2. Calcular uma taxa automaticamente;
|
||||
3. Pensar logicamente sobre qual UTXO seria válido utilizar;
|
||||
4. Combinar vários UTXOs, caso seja necessário;
|
||||
5. Ficar atento a mais erros nos comandos ``libbitcoinrpc`` ou no ``jansson``;
|
||||
6. Observar se há erros nas respostas RPC.
|
||||
|
||||
Se deseja continuar a expandir este exemplo, seria ótimo começar a lidar com as inadequações do programa.
|
||||
|
||||
## Escrevendo o sistema de transação
|
||||
|
||||
Agora estamos prontos para realizar o passo a passo do nosso plano
|
||||
|
||||
### Etapa 1: Solicitando um endereço e uma quantia
|
||||
|
||||
Inserir as informações é bem simples se usarmos os argumentos na linha de comando:
|
||||
``` c
|
||||
if(argc != 3) {
|
||||
|
||||
printf("ERROR: Only %i arguments! Correct usage is '%s [recipient] [amount]'\n",argc-1,argv[0]);
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
char *tx_recipient = argv[1];
|
||||
float tx_amount = atof(argv[2]);
|
||||
|
||||
printf("Sending %4.8f BTC to %s\n",tx_amount,tx_recipient);
|
||||
```
|
||||
|
||||
> :aviso: **ATENÇÃO:** Um programa real precisaria de uma higienização muito melhor dessas variáveis.
|
||||
|
||||
### Etapa 2: Definindo uma taxa arbitrária
|
||||
|
||||
Este exemplo colocamos uma taxa arbitrária de 0.0005 BTC para garantir que as transações do teste sejam processadas rapidamente:
|
||||
|
||||
``` c
|
||||
float tx_fee = 0.0005;
|
||||
float tx_total = tx_amount + tx_fee;
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** Um programa real calcularia uma taxa que minimizasse o custo, garantindo que a velocidade fosse aquela que o remetente estivesse disposto a utilizar.
|
||||
|
||||
### Etapa 3: Preparando nosso RPC
|
||||
|
||||
Obviamente, precisaremos preparar todas as nossas variáveis novamente, conforme discutido na sessão [§15.1: Acessando o Bitcoind usando C](15_1_Accessing_Bitcoind_with_C.md). Também precisaremos inicializar a nossa biblioteca, conectar o cliente RPC e preparar nosso objeto de resposta:
|
||||
``` c
|
||||
bitcoinrpc_global_init();
|
||||
rpc_client = bitcoinrpc_cl_init_params("bitcoinrpc", "YOUR-RPC-PASSWD", "127.0.0.1", 18332);
|
||||
btcresponse = bitcoinrpc_resp_init();
|
||||
```
|
||||
|
||||
### Etapa 4: Encontrando um UTXO
|
||||
|
||||
Para encontrar um UTXO, precisaremos chamar a função RPC ``listunspent``:
|
||||
``` c
|
||||
rpc_method = bitcoinrpc_method_init(BITCOINRPC_METHOD_LISTUNSPENT);
|
||||
bitcoinrpc_call(rpc_client, rpc_method, btcresponse, &btcerror);
|
||||
```
|
||||
|
||||
No entanto, o verdadeiro trabalho consiste em decodificar a resposta. Na seção anterior vimos que a biblioteca ``jansson`` era "um tanto quanto desajeitada" e esta é a razão: Precisamos criar (e limpar) um conjunto muito grande de objetos ``json_t`` para descobrir o que queremos.
|
||||
|
||||
Primeiro, precisamos nos recuperar o campo ``result`` do JSON:
|
||||
``` c
|
||||
json_t *lu_response = NULL;
|
||||
json_t *lu_result = NULL;
|
||||
|
||||
lu_response = bitcoinrpc_resp_get(btcresponse);
|
||||
lu_result = json_object_get(lu_response,"result");
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** Só obteremos um resultado se não houver nenhum erro. Aqui temos um momento para melhorar nossa verificação de erros no código que iremos colocar em produção.
|
||||
|
||||
Em seguida, vamos fazer um laço, examinando cada transação que não foi gasta, que aparece como um elemento em sua matriz do resultado JSON:
|
||||
``` c
|
||||
int i;
|
||||
|
||||
const char *tx_id = 0;
|
||||
int tx_vout = 0;
|
||||
double tx_value = 0.0;
|
||||
|
||||
for(i = 0 ; i < json_array_size(lu_result) ; i++) {
|
||||
|
||||
json_t *lu_data = NULL;
|
||||
lu_data = json_array_get(lu_result, i);
|
||||
|
||||
json_t *lu_value = NULL;
|
||||
lu_value = json_object_get(lu_data,"amount");
|
||||
tx_value = json_real_value(lu_value);
|
||||
```
|
||||
|
||||
O UTXO é grande o suficiente para pagar sua transação? Se sim, pegue-o!
|
||||
|
||||
> :warning: **ATENÇÃO:** Um programa em produção pensaria com mais cuidado sobre qual UTXO utilizar, com base no tamanho e em outros fatores. Provavelmente não pegaria apenas o primeiro mais simples e pronto.
|
||||
|
||||
``` c
|
||||
if(tx_value > tx_total) {
|
||||
|
||||
json_t *lu_txid = NULL;
|
||||
lu_txid = json_object_get(lu_data,"txid");
|
||||
tx_id = strdup(json_string_value(lu_txid));
|
||||
|
||||
json_t *lu_vout = NULL;
|
||||
lu_vout = json_object_get(lu_data,"vout");
|
||||
tx_vout = json_integer_value(lu_vout);
|
||||
|
||||
json_decref(lu_value);
|
||||
json_decref(lu_txid);
|
||||
json_decref(lu_vout);
|
||||
json_decref(lu_data);
|
||||
break;
|
||||
|
||||
}
|
||||
```
|
||||
Você também deve limpar os principais elementos do JSON:
|
||||
``` c
|
||||
}
|
||||
|
||||
json_decref(lu_result);
|
||||
json_decref(lu_response);
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** Um programa em produção também se certificaria de que os UTXOs são passíveis de serem `gastos`.
|
||||
|
||||
Se não encontramos nenhum UTXOs grande o suficiente, teremos que relatar este infortúnio ao usuário... E talvez, sugerir que ele deva usar um programa melhor, que irá mesclar os UTXOs de maneira correta.
|
||||
``` c
|
||||
if(!tx_id) {
|
||||
|
||||
printf("Very Sad: You don't have any UTXOs larger than %f\n",tx_total);
|
||||
exit(-1);
|
||||
}
|
||||
```
|
||||
|
||||
> **ATENÇÃO** Um programa em produção usaria sub-rotinas para este tipo de pesquisa, de forma que pudéssemos chamar vários RPCs de uma biblioteca de funções C. Vamos apenas colocar tudo em um `main` como parte da nossa filosofia KISS.
|
||||
|
||||
### Etapa 5: Criando um endereço de troco
|
||||
|
||||
Repita a metodologia padrão de pesquisa RPC para obter um endereço de troco:
|
||||
``` c
|
||||
rpc_method = bitcoinrpc_method_init(BITCOINRPC_METHOD_GETRAWCHANGEADDRESS);
|
||||
|
||||
if(!rpc_method) {
|
||||
|
||||
printf("ERROR: Unable to initialize listunspent method!\n");
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
bitcoinrpc_call(rpc_client, rpc_method, btcresponse, &btcerror);
|
||||
|
||||
if(btcerror.code != BITCOINRPCE_OK) {
|
||||
|
||||
printf("Error: listunspent error code %d [%s]\n", btcerror.code,btcerror.msg);
|
||||
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
lu_response = bitcoinrpc_resp_get(btcresponse);
|
||||
lu_result = json_object_get(lu_response,"result");
|
||||
char *changeaddress = strdup(json_string_value(lu_result));
|
||||
```
|
||||
A única diferença é quais informações específicas são extraídas do objeto JSON.
|
||||
|
||||
> :warning: **ATENÇÃO:** Aqui temos uma sub-rotina que seria bem legal: Abstrair toda a inicialização e chamada do método RPC.
|
||||
|
||||
### Etapa 6: Criando uma transação bruta
|
||||
|
||||
Criar a transação bruta real é outra parte complicada da programação da substituição do ``sendtoaddress``. Isso porque requer a criação de um objeto JSON complexo como parâmetro.
|
||||
|
||||
Para criarmos esses parâmetros corretamente, precisaremos revisar o que o RPC ``createrawtransaction`` espera que passemos como argumento. Felizmente, isso é fácil de determinar usando a funcionalidade ``bitcoin-cli help``:
|
||||
```
|
||||
$ bitcoin-cli help createrawtransaction
|
||||
createrawtransaction [{"txid":"id","vout":n},...] {"address":amount,"data":"hex",...} ( locktime )
|
||||
```
|
||||
|
||||
Para relembrar, as entradas serão uma matriz JSON contendo um objeto JSON para cada UTXO. Então, as saídas estarão todas em um objeto JSON. É mais fácil criar esses elementos JSON de dentro para fora, usando os comandos ``jansson``.
|
||||
|
||||
#### Etapa 6.1: Criando os parâmetros de entrada
|
||||
|
||||
Para criar o objeto de entrada para nosso UTXO, vamos usar o ``json_object`` e preencher com os valores-chave usando ``json_object_set_new`` (para referências recém-criadas) ou ``json_object_set`` (para referências já existentes):
|
||||
``` c
|
||||
json_t *inputtxid = NULL;
|
||||
inputtxid = json_object();
|
||||
|
||||
json_object_set_new(inputtxid,"txid",json_string(tx_id));
|
||||
json_object_set_new(inputtxid,"vout",json_integer(tx_vout));
|
||||
```
|
||||
|
||||
Pode-se notar que teremos que traduzir novamente cada tipo de variável C em um tipo de variável JSON usando a função apropriada, como ``json_string`` ou ``json_integer``.
|
||||
|
||||
Para criar o array de entrada para todos os UTXOs, vamos usar o ``json_array`` e, em seguida, preenchê-lo com os objetos usando o ``json_array_append``:
|
||||
``` c
|
||||
json_t *inputparams = NULL;
|
||||
inputparams = json_array();
|
||||
json_array_append(inputparams,inputtxid);
|
||||
```
|
||||
|
||||
#### Etapa 6.2: Criando os parâmetros de saída
|
||||
|
||||
Para criar a matriz de saída para a transação, vamos seguir o mesmo processo, criando um objeto JSON com ``json_object`` e, em seguida, vamos preenchê-lo com o ``json_object_set``:
|
||||
``` c
|
||||
json_t *outputparams = NULL;
|
||||
outputparams = json_object();
|
||||
|
||||
char tx_amount_string[32];
|
||||
sprintf(tx_amount_string,"%.8f",tx_amount);
|
||||
char tx_change_string[32];
|
||||
sprintf(tx_change_string,"%.8f",tx_value - tx_total);
|
||||
|
||||
json_object_set(outputparams, tx_recipient, json_string(tx_amount_string));
|
||||
json_object_set(outputparams, changeaddress, json_string(tx_change_string));
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** É possível pensar que teremos que inserir os valores do Bitcoin como sendo números, usando a função ``json_real``. Infelizmente, isso expõe um dos maiores problemas com a integração da biblioteca ``jansson`` e o Bitcoin. O Bitcoin só é válido até oito dígitos depois da casa decimal. Devemos nos lembrar que 0,00000001 BTC é um satoshi, e essa é a menor divisão possível de um Bitcoin. O tipo ``double`` no C oferecem mais dígitos do que precisamos, embora sejam frequentemente imprecisos depois das oito casas decimais. Se tentarmos convertê-los diretamente do nosso valor ``double`` no C (ou de um tipo ``float``, neste caso) para um valor Bitcoin, a imprecisão frequentemente criará um valor Bitcoin com mais de oito dígitos. Antes da versão Bitcoin Core 0.12, isso não era problema, e podíamos usar a função ``json_real``. Mas à partir dessa versão, se tentarmos usar a função ``createrawtransaction`` com mais do que oito dígitos, obteremos um erro e a transação não será criada. Como resultado, se o valor do Bitcoin _sempre_ se tornar um ``double`` ou ``float``, devemos deixar com apenas oito casas decimais antes de transformá-lo em uma ``string``. Obviamente, isso é um erro, portanto, certifique-se disso para que o código continue funcionando nas versões mais novas do Bitcoin Core.
|
||||
|
||||
#### Etapa 6.3: Criando a Matriz de Parâmetros
|
||||
|
||||
Para terminarmos de criar os parâmetros, só precisaremos agrupá-los em uma matriz JSON:
|
||||
``` c
|
||||
json_t *params = NULL;
|
||||
params = json_array();
|
||||
json_array_append(params,inputparams);
|
||||
json_array_append(params,outputparams);
|
||||
```
|
||||
|
||||
#### Etapa 6.4: Fazendo a chamada ao RPC
|
||||
|
||||
Vamos usar o método normal para criar uma chamada ao RPC:
|
||||
``` c
|
||||
rpc_method = bitcoinrpc_method_init(BITCOINRPC_METHOD_CREATERAWTRANSACTION);
|
||||
```
|
||||
Agora, porém, devemos adicionar os nossos parâmetros. Isso pode ser feito facilmente com a função ``bitcoinrpc_method_set_params``:
|
||||
``` c
|
||||
if(bitcoinrpc_method_set_params(rpc_method, params) != BITCOINRPCE_OK) {
|
||||
|
||||
fprintf(stderr, "Error: Could not set params for createrawtransaction");
|
||||
|
||||
}
|
||||
```
|
||||
Depois, é só executar o RPC e obter os resultados:
|
||||
``` c
|
||||
bitcoinrpc_call(rpc_client, rpc_method, btcresponse, &btcerror);
|
||||
|
||||
lu_response = bitcoinrpc_resp_get(btcresponse);
|
||||
lu_result = json_object_get(lu_response,"result");
|
||||
|
||||
char *tx_rawhex = strdup(json_string_value(lu_result));
|
||||
```
|
||||
### Etapa 7. Assinando a transação
|
||||
|
||||
É muito mais fácil atribuir um parâmetro simples a uma função. Basta criar uma matriz JSON e, em seguida, atribuir o parâmetro à matriz:
|
||||
``` c
|
||||
params = json_array();
|
||||
json_array_append_new(params,json_string(tx_rawhex));
|
||||
```
|
||||
Por fim, vamos assinar a transação seguindo o rigamarole típico para criar uma chamada RPC:
|
||||
``` c
|
||||
rpc_method = bitcoinrpc_method_init(BITCOINRPC_METHOD_SIGNRAWTRANSACTION);
|
||||
if(bitcoinrpc_method_set_params(rpc_method, params) != BITCOINRPCE_OK) {
|
||||
|
||||
fprintf(stderr, "Error: Could not set params for signrawtransaction");
|
||||
|
||||
}
|
||||
|
||||
json_decref(params);
|
||||
|
||||
bitcoinrpc_call(rpc_client, rpc_method, btcresponse, &btcerror);
|
||||
lu_response = bitcoinrpc_resp_get(btcresponse);
|
||||
```
|
||||
Novamente, usar a função ``jansson`` para acessar a saída pode ser complicado. Devemos lembrar que ``hex`` é parte de um objeto JSON, não um resultado independente, como era quando criamos a transação bruta. Claro, sempre podemos acessar essas informações a partir da ajuda da linha de comando: ``bitcoin-cli help signrawtransaction``
|
||||
``` c
|
||||
lu_result = json_object_get(lu_response,"result");
|
||||
json_t *lu_signature = json_object_get(lu_result,"hex");
|
||||
char *tx_signrawhex = strdup(json_string_value(lu_signature));
|
||||
json_decref(lu_signature);
|
||||
```
|
||||
> :warning: ***ATENÇÃO:*** Um programa em produção obviamente iria testar cuidadosamente a resposta de cada comando RPC para se certificar de que não teria erros. Isso é ainda mais verdadeiro para a função ``signrawtransaction``, porque podemos acabar com uma transação parcialmente assinada. Ou ainda pior, se não verificarmos os erros no objeto JSON, veremos apenas o ``hex`` e não iremos saber que ele não está assinado ou se está parcialmente assinado.
|
||||
|
||||
### Etapa 8. Enviando a transação
|
||||
|
||||
Agora podemos enviar a transação, usando todas as técnicas aprendidas anteriormente:
|
||||
``` c
|
||||
params = json_array();
|
||||
json_array_append_new(params,json_string(tx_signrawhex));
|
||||
|
||||
rpc_method = bitcoinrpc_method_init(BITCOINRPC_METHOD_SENDRAWTRANSACTION);
|
||||
|
||||
if(bitcoinrpc_method_set_params(rpc_method, params) != BITCOINRPCE_OK) {
|
||||
|
||||
fprintf(stderr, "Error: Could not set params for sendrawtransaction");
|
||||
|
||||
}
|
||||
|
||||
json_decref(params);
|
||||
|
||||
bitcoinrpc_call(rpc_client, rpc_method, btcresponse, &btcerror);
|
||||
lu_response = bitcoinrpc_resp_get(btcresponse);
|
||||
lu_result = json_object_get(lu_response,"result");
|
||||
|
||||
char *tx_newid = strdup(json_string_value(lu_result));
|
||||
|
||||
printf("Txid: %s\n",tx_newid);
|
||||
```
|
||||
|
||||
O código inteiro, com um _pouco_ mais verificação de erros, está disponível no Apêndice.
|
||||
|
||||
## Testando o código
|
||||
|
||||
O código completo pode ser encontrado no [diretório src/](src/15_2_sendtoaddress.c).
|
||||
|
||||
Compile-o como de costume:
|
||||
```
|
||||
$ cc sendtoaddress.c -lbitcoinrpc -ljansson -o sendtoaddress
|
||||
```
|
||||
Agora, é possível utilizá-lo para enviar fundos para um endereço:
|
||||
|
||||
```
|
||||
./sendtoaddress tb1qynx7f8ulv4sxj3zw5gqpe56wxleh5dp9kts7ns .001
|
||||
Txid: b93b19396f8baa37f5f701c7ca59d3128144c943af5294aeb48e3eb4c30fa9d2
|
||||
```
|
||||
Você pode ver as informações sobre esta transação que enviamos clicando [aqui](https://mempool.space/pt/testnet/tx/b93b19396f8baa37f5f701c7ca59d3128144c943af5294aeb48e3eb4c30fa9d2/).
|
||||
|
||||
## Resumo do Programando o Bitcoind usando C com bibliotecas RPC
|
||||
|
||||
Com acesso a uma biblioteca C, podemos criar programas com muito mais recursos quando comparados aos scripts no shell. Mas isso pode dar muito trabalho! Mesmo com 316 linhas de código, o ``sendtoaddress.c`` não cobre todos os detalhes necessários para transacionar bitcoins de forma segura e inteligente.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Aprenda mais sobre "Programando o Bitcoind usando C" na próxima sessão [15.3: Recebendo notificações usando C com a biblioteca ZMQ](15_3_Receiving_Bitcoind_Notifications_with_C.md).
|
155
pt/16_3_Receiving_Bitcoind_Notifications_with_C.md
Normal file
155
pt/16_3_Receiving_Bitcoind_Notifications_with_C.md
Normal file
@ -0,0 +1,155 @@
|
||||
|
||||
# 15.3 Recebendo notificações usando C com a biblioteca ZMQ
|
||||
|
||||
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho que pode estar aguardando revisão. Portanto, leitor, tenha cuidado.
|
||||
|
||||
As sessões [§15.1](15_1_Accessing_Bitcoind_with_C.md) e [§15.2](15_2_Programming_Bitcoind_with_C.md) introduziram as bibliotecas RPC e JSON no C e, também mostrou uma das vantagens de acessar os comandos RPC do Bitcoin por meio de uma linguagem de programação: A capacidade de criar programas razoavelmente complexos. Este capítulo apresenta uma terceira biblioteca, a [ZMQ](http://zeromq.org/) e, ao fazer isso, revela outra vantagem: A capacidade de monitorar as notificações. Iremos usá-la para codificar para ouvirmos a blockchain.
|
||||
|
||||
> :book: ***O que é ZMQ?*** O ZeroMQ (ZMQ) é uma biblioteca de mensagens assíncronas de alto desempenho que fornece uma fila de mensagens. A biblioteca oferece suporte a padrões de mensagens comuns (pub/sub, request/reply, client/server e outros) em uma variedade de transportes (TCP, in-process, inter-process, multicast, WebSocket e mais), tornando mensagens entre processos tão simples quanto mensagens entre threads. Podemos encontrar mais detalhes sobre as notificações do ZMQ e outros tipos de mensagens [neste repositório](https://github.com/Actinium-project/ChainTools/blob/master/docs/chainlistener.md).
|
||||
|
||||
## Configurando o ZMQ
|
||||
|
||||
Antes de podemos ouvir a blockchain, precisaremos configurar o ``bitcoind`` para permitir as notificações ZMQ. Por isso, precisamos instalar a biblioteca ZMQ para tirar proveito dessas notificações.
|
||||
|
||||
### Configurando o ``bitcoind`` para usar o ZMQ
|
||||
|
||||
O Bitcoin Core está pronto para ZMQ, mas devemos especificar os endpoints do ZMQ. O ZeroMQ publish-sockets prefixa cada item de dados com um prefixo de tópico arbitrário que permite aos clientes assinantes solicitarem apenas os itens com um prefixo correspondente. Existem atualmente quatro tópicos suportados pelo ``bitcoind``:
|
||||
```
|
||||
$ bitcoind --help | grep zmq | grep address
|
||||
-zmqpubhashblock=<address>
|
||||
-zmqpubhashtx=<address>
|
||||
-zmqpubrawblock=<address>
|
||||
-zmqpubrawtx=<address>
|
||||
```
|
||||
|
||||
Podemos executar o ``bitcoind`` com argumentos de linha de comando para endpoints ZMQ, como mostrado acima, mas também podemos criar um endpoint acessível adicionando linhas apropriadas ao nosso arquivo ``~/.bitcoin/bitcoin.conf`` e reiniciando o sistema.
|
||||
|
||||
```
|
||||
zmqpubrawblock=tcp://127.0.0.1:28332
|
||||
zmqpubrawtx=tcp://127.0.0.1:28333
|
||||
```
|
||||
Podemos então testar se os nossos endpoints estão funcionando usando o RPC ``getzmqnotifications``:
|
||||
|
||||
```
|
||||
$ bitcoin-cli getzmqnotifications
|
||||
[
|
||||
{
|
||||
"type": "pubrawblock",
|
||||
"address": "tcp://127.0.0.1:28332",
|
||||
"hwm": 1000
|
||||
},
|
||||
{
|
||||
"type": "pubrawtx",
|
||||
"address": "tcp://127.0.0.1:28333",
|
||||
"hwm": 1000
|
||||
}
|
||||
]
|
||||
```
|
||||
Nosso ``bitcoind`` agora irá emitir as notificações ZMQ
|
||||
|
||||
### Instalando o ZMQ
|
||||
|
||||
Para aproveitar essas notificações, precisamos de uma biblioteca ZMQ para usar com o C, portanto, estaremos usando uma nova biblioteca ZMQ ao invés da biblioteca ``libbitcoinrpc`` nesta seção, mas no futuro, podemos combinar ambas.
|
||||
|
||||
Felizmente, as bibliotecas ZMQ estão disponíveis por meio de pacotes Debian padrão:
|
||||
```
|
||||
$ sudo apt-get install libzmq3-dev
|
||||
$ sudo apt-get install libczmq-dev
|
||||
```
|
||||
Agora estamos pronto para escrever o código!
|
||||
|
||||
## Escrevendo o programa de notificação
|
||||
|
||||
O programa C à seguir é um cliente simples que se inscreve em um ponto da conexão ZMQ servido pelo ``bitcoind`` e lê as mensagens recebidas.
|
||||
|
||||
O programa requer dois parâmetros: O primeiro é o "servidor", que é o ponto de conexão TCP exposto pelo ``bitcoind``. O segundo é o "tópico", que atualmente é o ``zmqpubhashblock``,``zmqpubhashtx``, ``zmqpubrawblock`` ou ``zmqpubrawtx``. O tópico precisa ter suporte do ``bitcoin.conf`` e o endereço IP e a porta do servidor devem corresponder ao que está definido no arquivo de configuração.
|
||||
|
||||
``` c
|
||||
#include <czmq.h>
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
char *zmqserver;
|
||||
char *topic;
|
||||
|
||||
if(argc < 3) {
|
||||
printf("\nUSAGE:\nchainlistener <tcp://localhost:port> <topic>\n\n");
|
||||
return 0;
|
||||
} else {
|
||||
zmqserver = argv[1];
|
||||
topic = argv[2];
|
||||
}
|
||||
```
|
||||
Abriremos um soquete ZMQ para o servidor e para o tópico definido:
|
||||
``` c
|
||||
zsock_t *socket = zsock_new_sub(zmqserver, topic);
|
||||
assert(socket);
|
||||
```
|
||||
Depois, vamos esperar:
|
||||
``` c
|
||||
while(1) {
|
||||
zmsg_t *msg;
|
||||
int rc = zsock_recv(socket, "m", &msg);
|
||||
assert(rc == 0);
|
||||
|
||||
char *header = zmsg_popstr(msg);
|
||||
zframe_t *zdata = zmsg_pop(msg);
|
||||
unsigned int *no = (unsigned int*)zmsg_popstr(msg);
|
||||
|
||||
char *data = zframe_strhex(zdata);
|
||||
int len = zframe_size(zdata);
|
||||
printf("Size: %d\n", len);
|
||||
printf("Data: %s", data);
|
||||
printf("\nNo: %d\n", *no);
|
||||
|
||||
free(header);
|
||||
free(data);
|
||||
free(no);
|
||||
free(zdata);
|
||||
zmsg_destroy(&msg);
|
||||
sleep(1);
|
||||
}
|
||||
```
|
||||
Enquanto esperamos, observamos as mensagens no soquete ZMQ. Sempre que recebermos uma mensagem, iremos retirá-la da pilha, relatando o número, comprimento e, o os dados que foram importante para nós.
|
||||
|
||||
É isso!
|
||||
|
||||
Claro, quando terminar o processo, precisamos limpar tudo:
|
||||
``` c
|
||||
zsock_destroy(&socket);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Testando o código de notificação
|
||||
|
||||
O código-fonte completo está no [diretório src/](src/15_3_chainlistener.c) como de costume. Precisamos compilá-lo:
|
||||
```
|
||||
$ cc -o chainlistener chainlistener.c -I/usr/local/include -L/usr/local/lib -lzmq -lczmq
|
||||
```
|
||||
Depois, podemos executá-lo com os tópicos e endereços que definimos no nosso ``bitcoin.conf``:
|
||||
```
|
||||
$ ./chainlistener tcp://127.0.0.1:28333 rawtx
|
||||
Size: 250
|
||||
Data: 02000000000101F5BD2032E5A9E6650D4E411AD272E391F26AFC3C9102B7C0C7444F8F74AE86010000000017160014AE9D51ADEEE8F46ED2017F41CD631D210F2ED9C5FEFFFFFF0203A732000000000017A9147231060F1CDF34B522E9DB650F44EDC6C0714E4C8710270000000000001976A914262437B129CF8592AB2EDC59C07D19C57729F72888AC02483045022100AE316D5F21657E3525271DE39EB285D8A0E89A20AB6413824E88CE47DCD0EFE702202F61E10C2A8F4A7125D5EB63AEF883D8E3584A0ECED0D349283AABB6CA5E066D0121035A77FE575A9005E3D3FF0682E189E753E82FA8BFF0A20F8C45F06DC6EBE3421079111B00
|
||||
No: 67
|
||||
Size: 249
|
||||
Data: 0200000000010165C986992F7DAD22BBCE3FCF0BF546EDBC3C599618B04CFA22D9E64EF0CE4C030000000017160014B58E0A5CD68B249F1C407E9AAE9CD0332AAA3067FEFFFFFF02637932000000000017A914CCC47261489036CB6B9AA610857793FF5752E5378710270000000000001976A914262437B129CF8592AB2EDC59C07D19C57729F72888AC0247304402206CCC3F3B4BE01D4E532A01C2DC6BC3B53E4FFB6B494C8B87DD603EFC648A159902201653841E8B16A814DC375129189BB7CF01CFF7D269E91178645B6A97F5C7F4F10121030E20F3D2F172281B8DC747F007DF24B352248AC09E48CA64016942A8F01D317079111B00
|
||||
No: 68
|
||||
Size: 250
|
||||
Data: 02000000000101E889CFC1FFE127BA49F6C1011388606A194109AE1EDAAB9BEE215E123C14A7920000000017160014577B0B3C2BF91B33B5BD70AE9E8BD8144F4B87E7FEFFFFFF02C34B32000000000017A914A9F1440402B46235822639C4FD2F78A31E8D269E8710270000000000001976A914262437B129CF8592AB2EDC59C07D19C57729F72888AC02483045022100B46318F53E1DCE63E7109DB4FA54AF40AADFC2FEB0E08263756BC3B7A6A744CB02200851982AF87DBABDC3DFC3362016ECE96AECFF50E24D9DCF264AE8966A5646FE0121039C90FCB46AEA1530E5667F8FF15CB36169D2AD81247472F236E3A3022F39917079111B00
|
||||
No: 69
|
||||
Size: 250
|
||||
Data: 0200000000010137527957C9AD6CFF0C9A74597E6EFCD7E1EBD53E942AB2FA34A831046CA11488000000001716001429BFF05B3CD79E9CCEFDB5AE82139F72EB3E9DB0FEFFFFFF0210270000000000001976A914262437B129CF8592AB2EDC59C07D19C57729F72888AC231E32000000000017A9146C8D5FE29BFDDABCED0D6F4D8E82DCBFD9D34A8B8702483045022100F259846BAE29EB2C7A4AD711A3BC6109DE69AE91E35B14CA2742157894DD9760022021464E09C00ABA486AEAA0C49FEE12D2850DC03F57F04A1A9E2CC4D0F4F1459C012102899F24A9D60132F4DD1A5BA6DCD1E4E4B6C728927BA482C2C4E511679F60CA5779111B00
|
||||
No: 70
|
||||
.......
|
||||
```
|
||||
|
||||
### Resumo do capítulo Recebendo Notificações Usando C com a Biblioteca ZMQ
|
||||
|
||||
Ao usar a estrutura ZMQ, podemos receber notificações facilmente, inscrevendo-as em um ponto de conexão exposto pelo ``bitcoind`` através do nosso arquivo de configuração.
|
||||
|
||||
> :fire: ***Qual é o poder das notificações?*** Com as notificações, não dependemos mais dos usuários para emitir os comandos. Ou seja, podemos criar programas que monitoram o blockchain do Bitcoin e tomar as ações apropriadas quando certas coisas ocorrem. Isso, por sua vez, pode ser utilizado juntamente com os comandos RPC que programamos nas seções anteriores. Este também é um grande passo além do que poderíamos fazer com os scripts shell: Certamente, podemos criar scripts shell que fica ouvindo infinitamente, mas existem outras linguagens de programação que possuem ferramentas melhores para isso.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Saiba mais sobre "como Programar com RPC" no [Capítulo 16: Programando Bitcoin com Libwally](16_0_Programming_with_Libwally.md).
|
Loading…
x
Reference in New Issue
Block a user