
# 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).