From 4fb508a05417a7ecdd72f648220f67e901444bf0 Mon Sep 17 00:00:00 2001 From: KoreaComK Date: Fri, 6 Aug 2021 11:18:29 -0300 Subject: [PATCH 01/14] Chapter 16 translation finished --- pt/16_0_Programming_with_Libwally.md | 29 ++ pt/16_1_Setting_Up_Libwally.md | 196 +++++++++ pt/16_2_Using_BIP39_in_Libwally.md | 106 +++++ pt/16_3_Using_BIP32_in_Libwally.md | 142 +++++++ pt/16_4_Using_PSBTs_in_Libwally.md | 378 ++++++++++++++++++ pt/16_5_Using_Scripts_in_Libwally.md | 179 +++++++++ pt/16_6_Using_Other_Functions_in_Libwally.md | 126 ++++++ ..._7_Integrating_Libwally_and_Bitcoin-CLI.md | 330 +++++++++++++++ 8 files changed, 1486 insertions(+) create mode 100644 pt/16_0_Programming_with_Libwally.md create mode 100644 pt/16_1_Setting_Up_Libwally.md create mode 100644 pt/16_2_Using_BIP39_in_Libwally.md create mode 100644 pt/16_3_Using_BIP32_in_Libwally.md create mode 100644 pt/16_4_Using_PSBTs_in_Libwally.md create mode 100644 pt/16_5_Using_Scripts_in_Libwally.md create mode 100644 pt/16_6_Using_Other_Functions_in_Libwally.md create mode 100644 pt/16_7_Integrating_Libwally_and_Bitcoin-CLI.md diff --git a/pt/16_0_Programming_with_Libwally.md b/pt/16_0_Programming_with_Libwally.md new file mode 100644 index 0000000..735b8ae --- /dev/null +++ b/pt/16_0_Programming_with_Libwally.md @@ -0,0 +1,29 @@ +# Capítulo 16: Programando com Libwally + +O capítulo anterior apresentou três bibliotecas C, para RPC, JSON e ZMQ, todas destinadas a interagir diretamente com o `bitcoind`, assim como você vem fazendo desde o início. Mas, às vezes você pode querer codificar sem acesso direto a um `bitcoind`. Isso pode ser devido a um cliente offline ou apenas porque você deseja manter algumas funcionalidades internas de seu programa C. Você também pode querer se aprofundar na funcionalidade da carteira, como criação de palavras mnemônicas ou derivação de endereços. É aí que entra Libwally: é uma biblioteca de carteira para C, C ++, Java, NodeJS ou Python, com wrappers também disponíveis para outras linguagens, como Swift. + +Este capítulo aborda a funcionalidade possível dentro do Libwally, a maioria das quais complementa o trabalho que você fez através do acesso RPC ao `bitcoind`, mas algumas das quais o replicam. Ele também mostra como integrar esse trabalho com os clientes RPC com os quais você está mais familiarizado. No entanto, observe que esta é apenas uma introdução básica ao Libwally. Vários de seus conjuntos de funções mais importantes são destacados, mas nunca fazemos mais do que enfiar os pés no chão. Se você acha suas funções úteis ou intrigantes, então você precisará se aprofundar muito mais profundamente do que este curso pode cobrir. + +## Objetivos deste capítulo + +Depois de trabalhar neste capítulo, um desenvolvedor será capaz de: + + * Usar as funções da carteira com o Libwally; + * Realizar manipulações de PSBTs e transações com o Libwally; + * Implementar designs que combinem o Libwally e o RPC. + +Os objetivos secundários do capítulo incluem a capacidade de: + + * Compreender palavras mnemônicas BIP39; + * Conhecer mais sobre as carteiras hierárquicas BIP32; + * Sintetizar a profundidade funcional do Libwally. + +## Tabela de Conteúdo + + * [Seção 1: Configurando o Libwally](16_1_Setting_Up_Libwally.md) + * [Seção 2: Usando o BIP39 no Libwally](16_2_Using_BIP39_in_Libwally.md) + * [Seção 3: Usando o BIP32 no Libwally](16_3_Using_BIP32_in_Libwally.md) + * [Seção 4: Usando o PSBTs no Libwally](16_4_Using_PSBTs_in_Libwally.md) + * [Seção 5: Usando Scripts no Libwally](16_5_Using_Scripts_in_Libwally.md) + * [Seção 6: Usando Outras Funções no Libwally](16_6_Using_Other_Functions_in_Libwally.md) + * [Seção 7: Integrando o Libwally ao Bitcoin-CLI](16_7_Integrating_Libwally_and_Bitcoin-CLI.md) \ No newline at end of file diff --git a/pt/16_1_Setting_Up_Libwally.md b/pt/16_1_Setting_Up_Libwally.md new file mode 100644 index 0000000..990b800 --- /dev/null +++ b/pt/16_1_Setting_Up_Libwally.md @@ -0,0 +1,196 @@ +# 16.1: Configurando a Libwally + +> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. + +Esta primeira seção explicará como fazer o download da Biblioteca Libwally C e como colocá-la em funcionamento. + +> :book: ***O que é a Libwally?*** A Libwally é uma biblioteca de primitivas útil para a criação de carteiras que é totalmente multiplataforma, de modo que as mesmas funções possam ser usadas em qualquer lugar. Existem [documentação online](https://wally.readthedocs.io/en/latest/), caso esteja interessado. A Libwally está disponível como parte do [Elements Project](https://github.com/ElementsProject) da Blockstream. + +## Instalando o Libwally + +Como de costume, precisaremos de alguns pacotes no nosso sistema: +``` +$ sudo apt-get install git +$ sudo apt-get install dh-autoreconf +``` +Podemos então fazer o download do Libwally com base no seu repositório Git: +``` +$ git clone https://github.com/ElementsProject/libwally-core +``` +Afterward, you can begin the configuration process: +Depois, podemos começar com o processo de configuração. +``` +$ ./tools/autogen.sh +``` +Como no ```libbitcoinrpc```, podemos querer instalar no caminho `/usr/include` e no `/usr/lib` para facilitar o uso. Basta modificar a linha apropriada no arquivo `configure` do programa: +``` +< ac_default_prefix=/usr +--- +> ac_default_prefix=/usr/local +``` +Depois, podemos terminar nossa preparação: +``` +$ ./configure +$ make +``` +Agora, podemos verificar se os testes estão funcionando: +``` +$ make check +Making check in src +make[1]: Entering directory '/home/standup/libwally-core/src' +Making check in secp256k1 +make[2]: Entering directory '/home/standup/libwally-core/src/secp256k1' +make check-TESTS +make[3]: Entering directory '/home/standup/libwally-core/src/secp256k1' +make[4]: Entering directory '/home/standup/libwally-core/src/secp256k1' +============================================================================ +Testsuite summary for libsecp256k1 0.1 +============================================================================ +# TOTAL: 0 +# PASS: 0 +# SKIP: 0 +# XFAIL: 0 +# FAIL: 0 +# XPASS: 0 +# ERROR: 0 +============================================================================ +make[4]: Leaving directory '/home/standup/libwally-core/src/secp256k1' +make[3]: Leaving directory '/home/standup/libwally-core/src/secp256k1' +make[2]: Leaving directory '/home/standup/libwally-core/src/secp256k1' +make[2]: Entering directory '/home/standup/libwally-core/src' +make check-TESTS check-local +make[3]: Entering directory '/home/standup/libwally-core/src' +make[4]: Entering directory '/home/standup/libwally-core/src' +PASS: test_bech32 +PASS: test_psbt +PASS: test_psbt_limits +PASS: test_tx +============================================================================ +Testsuite summary for libwallycore 0.7.8 +============================================================================ +# TOTAL: 4 +# PASS: 4 +# SKIP: 0 +# XFAIL: 0 +# FAIL: 0 +# XPASS: 0 +# ERROR: 0 +============================================================================ +make[4]: Leaving directory '/home/standup/libwally-core/src' +make[3]: Nothing to be done for 'check-local'. +make[3]: Leaving directory '/home/standup/libwally-core/src' +make[2]: Leaving directory '/home/standup/libwally-core/src' +make[1]: Leaving directory '/home/standup/libwally-core/src' +make[1]: Entering directory '/home/standup/libwally-core' +make[1]: Nothing to be done for 'check-am'. +make[1]: Leaving directory '/home/standup/libwally-core' +``` +Finalmente, podemos instalar: +``` +$ sudo make install +``` + +## Nos preparando para a Libwally + +Então, como usamos a Libwally em nosso programa que estamos construindo? Como de costume, precisaremos incluir os arquivos e vincular as bibliotecas apropriadas em nosso código. + +### Incluindo os arquivos + +Há um número considerável de arquivos que podemos incluir: + +``` +$ ls /usr/include/wally* +/usr/include/wally_address.h /usr/include/wally_bip39.h /usr/include/wally_elements.h /usr/include/wally_script.h +/usr/include/wally_bip32.h /usr/include/wally_core.h /usr/include/wally.hpp /usr/include/wally_symmetric.h +/usr/include/wally_bip38.h /usr/include/wally_crypto.h /usr/include/wally_psbt.h /usr/include/wally_transaction.h +``` +Felizmente, os nomes dos arquivos correspondem amplamente às seções da [documentação](https://wally.readthedocs.io/en/latest/), então devemos ser capazes de incluir os arquivos corretos com base no que estamos fazendo, depois de incluir o onipresente `wally_core.h`. + +### Vinculando as bibliotecas + +Também precisaremos vincular as bibliotecas apropriadas: +``` +$ ls /usr/lib/libsecp* /usr/lib/libwally* +/usr/lib/libsecp256k1.a /usr/lib/libwallycore.la /usr/lib/libwallycore.so.0 +/usr/lib/libsecp256k1.la /usr/lib/libwallycore.so /usr/lib/libwallycore.so.0.0.0 +``` +Usaremos principalmente a `libwallycore`. + +## Configurando um programa Libwally + +Comparado com algumas das bibliotecas anteriores, a Libwally é ridiculamente fácil de ser inicializada: +``` +lw_response = wally_init(0); +``` +E então, quando terminarmos, há uma função útil para limpar qualquer memória alocada: +``` +wally_cleanup(0); +``` +Em ambos os casos, o argumento é para flags, mas atualmente está definido como `0`. + +## Testando um programa de teste da Libwally + +O diretório src contém o arquivo [testwally.c](src / 16_1_testwally.c), que apenas mostra como funcionam as funções de inicialização e de limpeza. + +Podemos compilá-lo da seguinte maneira: +``` +$ cc testwally.c -lwallycore -o testwally +``` +Depois, podemos executá-lo: +``` +$ ./testwally +Startup: 0 +``` +O valor "Startup" é o retorno do comando `wally_init`. O valor `0` pode inicialmente parecer desanimador, mas é o que desejamos ver no momento: +``` +include/wally_core.h:#define WALLY_OK 0 /** Success */ +``` + +## Instalando o Libsodium + +Também precisamos instalar o Libsodium para obter acesso a um gerador de números aleatórios de alta qualidade para fins de teste. + +> :warning: **AVISO:** A geração de números aleatórios pode ser um dos maiores pontos de vulnerabilidade em qualquer software do Bitcoin. Se fizermos isso de maneira errada, podemos export nossos usuários a ataques porque eles acabam tendo chaves privadas do Bitcoin inseguras, e isso não é um [problema teórico](https://github.com/BlockchainCommons/SmartCustodyBook/blob/master/manuscript/ 03-adversaries.md # adversary-systemic-key-compromise). A BlockchainInfo gerou incorretamente 0,0002% das suas chaves, o que resultou na perda temporária de 250 Bitcoins. Resumindo: Precisamos nos certificar de estar totalmente confortável com a geração de números aleatórios. Podemos usar o Libsodium ou qualquer outro método TRNG ainda mais robusto. + +Podemos baixar um [Libsodium tarball](https://download.libsodium.org/libsodium/releases/) e seguir as instruções em [instalação do Libsodium](https://doc.libsodium.org/installation) para deixarmos tudo pronto em nosso computador. + +Primeiro, descompactamos: +``` +$ tar xzfv /tmp/libsodium-1.0.18-stable.tar.gz +``` +Então, ajustamos o arquivo `configure` exatamente como fizemos nas outras bibliotecas até o momento: +``` +< ac_default_prefix=/usr +--- +> ac_default_prefix=/usr/local +``` +Finalmente, usamos os comandos `make`,`check` e `install`: +``` +$ make +$ make check +... +============================================================================ +Testsuite summary for libsodium 1.0.18 +============================================================================ +# TOTAL: 77 +# PASS: 77 +# SKIP: 0 +# XFAIL: 0 +# FAIL: 0 +# XPASS: 0 +# ERROR: 0 +============================================================================ +... +$ sudo make install +``` +Este curso usará apenas `libsodium` para um pequeno (mas crucial!) bit de geração de entropia, mas precisamos prestar muita atenção na próxima seção. + +## Resumo: Configurando a Libwally + +Ao instalar os includes e as bibliotecas da Libwally (e do Libsodium), ganhamos acesso a uma série de funções criptográficas e de carteira, que podem complementar nossas bibliotecas RPC e ZMG (ou nossa linha de comando `bitcoin-cli`). + +Então, o que exatamente podemos fazer agora? É para dar essa resposta que temos todas as seções deste capítulo. + +## O Que Vem Depois? + +Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.2: Usando o BIP39 no Libwally](16_2_Using_BIP39_in_Libwally.md). \ No newline at end of file diff --git a/pt/16_2_Using_BIP39_in_Libwally.md b/pt/16_2_Using_BIP39_in_Libwally.md new file mode 100644 index 0000000..4669828 --- /dev/null +++ b/pt/16_2_Using_BIP39_in_Libwally.md @@ -0,0 +1,106 @@ +# 16.2: Usando o BIP39 no Libwally + +> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. + +Um dos maiores poderes de Libwally é que ele pode revelar o trabalho oculto da geração de seeds, chaves privadas e, também, de endereços. Para começar, ele suporta o [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki), que é o BIP que define códigos mnemônicos para o Bitcoin, algo que é totalmente incompatível, na época, com o Bitcoin Core. + +> :book: ***O que é um código mnemônico?*** Os endereços de Bitcoin (e suas chaves privadas correspondentes e as suas seeds) são listas longas e ininteligíveis de caracteres e números, que não são apenas impossíveis de serem lembrados, mas também fáceis de serem digitados erroneamente. Os códigos mnemônicos são uma solução para isso que permitem aos usuários gravar 12 (ou 24) palavras em inglês, algo que é muito menos sujeito a erros. Esses códigos podem ser usados para restaurar totalmente uma seed BIP32 que é a base de uma carteira Determinística Hierárquica. + +> :book: ***O que é uma seed?*** Nós falamos brevemente das seeds na seção [§3.5: Compreendendo o descritor](03_5_Understanding_the_Descriptor.md). É o número aleatório usado para gerar uma sequência inteira de chaves privadas (e, portanto, endereços) em uma carteira Determinística Hierárquica. Voltaremos às seeds na próxima seção, onde falaremos sobre as carteiras Determinísticas Hierárquicas e a Libwally. Por enquanto, apenas é necessário saber que um código mnemônico BIP39 corresponde à seed para uma carteira determinística hierárquica do BIP32. + +## Criando Códigos Mnemônicos + +Todas as chaves Bitcoin começam com a entropia. Este primeiro uso de Libwally, e os mnemônicos BIP39, mostram como gerar entropia e obter um código mnemônico a partir disso. + +> :book: ***O que é entropia?*** Entropia é uma maneira sofisticada de dizer aleatoriedade, mas é uma aleatoriedade medida cuidadosamente que é usada como a base de um número aleatório gerado verdadeiramente (no inglês, true-random-number generated, TRG). É medido em "bits", com mais bits de entropia resultando em mais aleatoriedade (e, portanto, mais proteção para o que está sendo gerado). Para o Bitcoin, a entropia é a base de nossa seed, que em uma carteira Determinística Hierárquica que gera todos os seus endereços. + +Sempre começaremos a trabalhar com a Libwally inicializando a biblioteca e testando os resultados, conforme demonstrado pela primeira vez na seção [§16.1](16_1_Setting_Up_Libwally.md): +``` + int lw_response; + + lw_response = wally_init(0); + + if (lw_response) { + + printf("Error: Wally_init failed: %d\n",lw_response); + exit(-1); + + } +``` +Agora estamos prontos para a entropia. + +### Criando a Entropia + +Usando o `libsodium`, podemos criar a entropia com o comando `randombytes_buf`: +``` + unsigned char entropy[16]; + randombytes_buf(entropy, 16); +``` +Este exemplo, que será a única maneira de usarmos a biblioteca `libsodium`, cria 16 bytes de entropia. Geralmente, para criar um código mnemônico seguro, devemos usar entre 128 e 256 bits de entropia, que é 16 a 32 bytes. + +> :warning: **AVISO:** Mais uma vez, certifique-se de estar muito confortável com o método de geração de entropia antes de usá-lo em um programa do mundo real. + +### Traduzindo para um mnemônico + +16 bytes de entropia são suficientes para criar um código Mnemônico de 12 caracteres, que é feito com a função `bip39_mnemonic_from_bytes` da Libwally: +``` + char *mnem = NULL; + lw_response = bip39_mnemonic_from_bytes(NULL,entropy,16,&mnem); +``` +Observe que temos que passar o tamanho do byte, então se quiser aumentar o tamanho da entropia, para gerar uma frase mnemônica mais longa, também precisaria aumentar o valor nesta função. + +> **NOTA:** Existem listas de palavras mnemônicas para diferentes idiomas! O padrão é usar a lista do idioma inglês, que é a variável `NULL` nesses comandos mnemônicos da Libwally, mas podemos, alternativamente, solicitar um idioma diferente! + +É isso! Nós criamos uma frase mnemônica! + +> :book: ***Como a frase mnemônica é criada?*** Podemos aprender mais sobre isso no [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki), mas se preferir, Greg Walker tem um [excelente exemplo](https://learnmeabitcoin.com/technical/mnemonic): De maneira geral, adicionamos uma soma de verificação e convertemos cada conjunto de 11 bits em uma palavra da lista de palavras. Podemos fazer isso com os comandos `bip39_get_wordlist` e `bip39_get_word` se não confiarmos no comando `bip39_mnemonic_from_bytes`. + +### Traduzindo para uma seed + +Existem algumas funções, como o `bip32_key_from_seed` (que veremos na próxima seção) que requerem que tenhamos os bits ao invés do Mnemônico. As duas coisas são funcionalmente idênticas, se temos a seed, pode gerar o mnemônico e vice-versa. + +Se você precisarmos gerar a seed a partir do nosso mnemônico, basta usar o comando `bip39_mnemonic_to_seed`: +``` + unsigned char seed[BIP39_SEED_LEN_512]; + size_t seed_len; + + lw_response = bip39_mnemonic_to_seed(mnem,NULL,seed,BIP39_SEED_LEN_512,&seed_len); +``` +Observe que todas as seeds do BIP39 têm 512 bytes; no entanto, devemos definir o tamanho de nossa variável apropriadamente e passar o tamanho para o `bip39_mnemonic_to_seed`. + +### Mostrando na Tela a Nossa Seed + +Se quisermos ver como nossa semente se parece em hexadecimal, podemos usar a função `wally_hex_from_bytes` para transformar nossa seed em um código hexadecimal legível (mas isso não é muito bom para pessoas): +``` + char *seed_hex; + wally_hex_from_bytes(seed,sizeof(seed),&seed_hex); + printf("Seed: %s\n",seed_hex); +``` +Se dizermos tudo certo, devemos obter uma seed de 64 bytes. (Essa é a variável `BIP39_SEED_LEN_512` que estamos usando, que define um comprimento de seed padrão de 512 bits ou 64 bytes.) + +> :warning: **ATENÇÃO:** Definitivamente devemos testar se o comprimento da nossa seed é de 64 bytes de alguma forma, porque é fácil errar em alguma coisa, por exemplo, usando o tipo de variável errado quando executamos o `bip39_mnemonic_to_seed`. + +## Testando o Código Mnemônico + +O código completo para gerar entropia, gerar um mnemônico BIP39, validar o mnemônico e gerar uma seed pode ser encontrado no [diretório src/](src/16_2_genmnemonic.c). Podemos fazer o download e compilar: +``` +$ cc genmnemonic.c -lwallycore -lsodium -o genmnemonic +``` +Então podemos executar o teste: +``` +Mnemonic: parent wasp flight sweet miracle inject lemon matter label column canyon trend +Mnemonic validated! +Seed: 47b04cfb5d8fd43d371497f8555a27a25ca0a04aafeb6859dd4cbf37f6664b0600c4685c1efac29c082b1df29081f7a46f94a26f618fc6fd38d8bc7b6cd344c7 +``` + +## Resumo: Usando o BIP39 no Libwally + +O BIP39 permite que possamos gerar um conjunto de 12-24 palavras Mnemônicas a partir de uma seed e a biblioteca Libwally também permite que a validemos! + +> :fire: ***Qual é o poder do BIP39?*** Seeds de Bitcoin e chaves privadas estão sujeitas a todos os tipos de perda. Se digitarmos errado um único dígito, nosso dinheiro será perdido para sempre. Palavras mnemônicas são uma forma muito mais amigável de representar os mesmos dados, mas como são palavras no idioma de escolha do usuário, são menos sujeitas a erros. O poder do BIP39 é, portanto, melhorar a acessibilidade, usabilidade e segurança do Bitcoin. + +> :fire: ***Qual é o poder do BIP39 na Libwally?*** O Bitcoind atualmente não suporta palavras mnemônicas, então usar a Libwally pode permitir que geremos palavras mnemônicas em conjunto com endereços mantidos no `bitcoind`, embora como veremos na seção §16.7, é necessário um pouco de gambiarra para importar suas chaves para o Bitcoin Core. + +## O Que Vem Depois? + +Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.3: Usando o BIP32 no Libwally](16_3_Using_BIP32_in_Libwally.md). \ No newline at end of file diff --git a/pt/16_3_Using_BIP32_in_Libwally.md b/pt/16_3_Using_BIP32_in_Libwally.md new file mode 100644 index 0000000..040cae3 --- /dev/null +++ b/pt/16_3_Using_BIP32_in_Libwally.md @@ -0,0 +1,142 @@ +# 16.3: Usando o BIP32 no Libwally + +> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. + +Na seção [§16.2](16_2_Using_BIP39_in_Libwally.md), fomos capazes de usar a entropia para gerar uma semente e nosso mnemônico relacionado. Como devemos nos lembrar da seção [§3.5: Compreendendo o descritor](03_5_Understanding_the_Descriptor.md), uma seed é a base de uma Carteira Determinística Hierárquica (no inglês Hierchical Deterministic, HD), onde aquela única seed pode ser usada para gerar muitos endereços. Então, como passamos da seed para os endereços reais? É aí que entra o [BIP32](https://en.bitcoin.it/wiki/BIP_0032). + +## Criando uma raiz HD + +Para criar um endereço HD, é necessário começar com uma seed e, em seguida, descer na hierarquia até o ponto em que criamos os endereços. + +Isso começa com bastante facilidade, conosco gerando uma seed, o que já fizemos na seção anterior: +``` + unsigned char entropy[16]; + randombytes_buf(entropy, 16); + + char *mnem = NULL; + lw_response = bip39_mnemonic_from_bytes(NULL,entropy,16,&mnem); + + unsigned char seed[BIP39_SEED_LEN_512]; + size_t seed_len; + lw_response = bip39_mnemonic_to_seed(mnem,NULL,seed,BIP39_SEED_LEN_512,&seed_len); +``` +### Gerando uma chave raiz + +Com uma seed em mãos, podemos gerar uma chave mestra estendida com a função `bip32_key_from_seed_alloc` (ou, alternativamente, com o comando `bip32_key_from_seed`, que não faz o `alloc`): +``` + struct ext_key *key_root; + lw_response = bip32_key_from_seed_alloc(seed,sizeof(seed),BIP32_VER_TEST_PRIVATE,0,&key_root); +``` +Como podemos ver, precisaremos dizer ao comando qual versão da chave retornar, neste caso `BIP32_VER_TEST_PRIVATE`, uma chave privada testnet. + +> :link: **TESTNET vs MAINNET:** Na mainnet, iríamos passar `BIP32_VER_MAIN_PRIVATE`. + +### Gerando a xpub e a xprv + +Sempre que tivermos uma chave em mãos, podemos transformá-la em chaves xpub ou xprv para distribuição com o comando `bip32_key_to_base58`. Basta dizer se desejamos uma chave `PRIVATE` (xprv) ou `PUBLIC` (xpub): +``` + char *xprv; + lw_response = bip32_key_to_base58(key_root, BIP32_FLAG_KEY_PRIVATE, &xprv); + + char *xpub; + lw_response = bip32_key_to_base58(key_root, BIP32_FLAG_KEY_PUBLIC, &xpub); +``` + +## Compreendendo a hierarquia + +Antes de prosseguir, precisamos entender como funciona a hierarquia de uma carteira HD. Conforme discutido na seção [§3.5](03_5_Understanding_the_Descriptor.md), um caminho de derivação descreve a árvore que seguimos para obter uma chave hierárquica, então `[0/1/0]` é o 0º filho do 1º filho do 0º filho de uma chave raiz. Às vezes, parte dessa derivação é marcada com `'` s ou `h`s para mostrar derivações endurecidas, que aumentam a segurança: `[0'/1'/0']`. + +No entanto, para carteiras HD, cada um desses níveis da hierarquia é usado de uma forma muito específica. Isso foi definido originalmente no [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) e foi atualizado posteriormente para o Segwit no [BIP84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki). + +Ao todo, um caminho de derivação BIP32 é definido para ter cinco níveis: + +1. **Objetivo.** Isso geralmente é definido como `44'` ou `84'`, dependendo do BIP que estamos seguindo; +2. **Moeda.** Para bitcoins Mainnet, é `0'`, para testnet é `1'`; +3. **Conta.** Uma carteira pode conter várias contas discretas, começando com `0'`; +4. **Troco.** Os endereços externos (para distribuição) são definidos como `0`, enquanto os endereços internos (para troco) são definidos como `1`; +5. **Índice.** O enésimo endereço da hierarquia, começando com `0`. + +Então, na testnet, o endereço zero para um endereço externo para a conta zero para moedas testnet usando os padrões BIP84 é `[m/84'/1'/0'/0/0]`. Esse é o endereço que criaremos neste momento. + +> :link: **TESTNET vs MAINNET:** Para a mainnet, seria `[m/84'/0'/0'/0/0]`. + +### Entendendo a Hierarquia no Bitcoin Core + +Estaremos usando a hierarquia acima para todas as chaves de HD na Libwally, mas observe que este padrão não é usado no `bitcoin-cli` do Bitcoin Core, que ao invés disso usa `[m/0'/0'/0']` para o enésimo endereço externo e `[m/0'/1'/0']` para o enésimo endereço de troco. + +## Gerando um endereço + +Para gerar um endereço, devemos explorar toda a hierarquia. + +### Gerando uma chave da conta + +Uma maneira de fazer isso é usar a função `bip32_key_from_parent_path_alloc` para descer vários níveis de uma hierarquia. Podemos incorporar os níveis em uma matriz: +``` + uint32_t path_account[] = {BIP32_INITIAL_HARDENED_CHILD+84, BIP32_INITIAL_HARDENED_CHILD+1, BIP32_INITIAL_HARDENED_CHILD}; +``` +Aqui, veremos a enésima filha endurecida (essa é a conta) ou a primeira filha endurecida (que são as moedas testnet) da 84ª filha endurecida (esse é o padrão BIP84): `[m/84'/1'/0']`. + +Podemos então usar esse caminho para gerar uma nova chave a partir da nossa antiga chave: +``` + struct ext_key *key_account; + lw_response = bip32_key_from_parent_path_alloc(key_root,path_account,sizeof(path_account),BIP32_FLAG_KEY_PRIVATE,&key_account); +``` +Sempre que tiviermos uma nova chave, poderemos usá-la para gerar novas chaves xprv e xpub, se desejarmos: +``` + lw_response = bip32_key_to_base58(key_account, BIP32_FLAG_KEY_PRIVATE, &a_xprv); + lw_response = bip32_key_to_base58(key_account, BIP32_FLAG_KEY_PUBLIC, &a_xpub); +``` + +### Gerando uma chave de endereço + +Alternativamente, podemos usar a função `bip32_key_from_parent_alloc`, que apenas desce um nível da hierarquia por vez. O exemplo a seguir desce para o enésimo filho da chave da conta (que é o endereço externo) e, em seguida, o enésimo filho dessa chave. Isso seria útil porque poderíamos continuar gerando o primeiro endereço, o segundo endereço e assim por diante a partir dessa chave externa: +``` + struct ext_key *key_external; + lw_response = bip32_key_from_parent_alloc(key_account,0,BIP32_FLAG_KEY_PRIVATE,&key_external); + + struct ext_key *key_address; + lw_response = bip32_key_from_parent_alloc(key_external,0,BIP32_FLAG_KEY_PRIVATE,&key_address); +``` +> :warning: **AVISO:** Em algum ponto desta hierarquia, podemos decidir gerar o `BIP32_FLAG_KEY_PUBLIC` ao invés do `BIP32_FLAG_KEY_PRIVATE`. Obviamente, essa decisão será baseada na nossa segurança e nas nossas necessidades, mas precisamos lembrar de que só precisamos de uma chave pública para gerar o endereço real. + +### Gerando um endereço + +Finalmente, estamos pronto para gerar um endereço a partir de sua chave final. Tudo que fazemos é executar `wally_bip32_to_addr_segwit` usando nossa chave final e uma descrição de que tipo de endereço é este. +``` + char *segwit; + lw_response = wally_bip32_key_to_addr_segwit(key_address,"tb",0,&segwit); + + printf("[m/84'/1'/0'/0/0]: %s\n",segwit); +``` + +> :link: **TESTNET vs MAINNET:** O argumento `tb` define um endereço Testnet. Para a Mainnet, usamos o `bc`. + +Há também uma função `wally_bip32_key_to_address`, que pode ser usada para gerar um endereço legado ou um endereço Segwit aninhado. + +## Testando o Código HD + +O código para esses exemplos de HD pode, como de costume, ser encontrado no [diretório src/](src / 16_3_genhd.c). + +Podemos compilá-lo e testá-lo: +``` +$ cc genhd.c -lwallycore -lsodium -o genhd +$ ./genhd +Mnemonic: behind mirror pond finish borrow wood park foam guess mail regular reflect +Root xprv key: tprv8ZgxMBicQKsPdLFXmZ6VegTxcmeieNpRUq8J2ahXxSaK2aF7CGqAc14ZADLjdHJdCr8oR2Zng9YH1x1A7EBaajQLVGNtxc4YpFejdE3wyj8 +Root xpub key: tpubD6NzVbkrYhZ4WoHKfCm64685BoAeoi1L48j5K6jqNiNhs4VspfeknVgRLLiQJ3RkXiA9VxguUjmEwobtmrXNbhXsPHfm9W5HJR9DKRGaGJ2 +Account xprv key: tprv8yZN7h6SPvJXrhAk56z6cwHQE6qZBRreB9fqqZJ1Xd1nLci3Rw8HTmqNkpFNgf3eZx8hYzhFWafUhHSt3HgF13aHvCE6kveS7gZAyfQwMDi +Account xpub key: tpubDWFQG78gYHzCkACXxkeh2LwWo8MVLm3YkTGd85LJwtpBB6xp4KwseGTEvxjeZNhnCNPdfZqRcgcZZAka4tD3xGS2J53WKHPMRhG357VKsqT +[m/84'/1'/0'/0/0]: tb1q0knqq26ek59pfl7nukzqr28m2zl5wn2f0ldvwu +``` + +## Resumo: Usando o BIP32 no Libwally + +Uma carteira HD permite gerar um grande número de chaves a partir de uma única seed. Agora sabemos como essas chaves são organizadas no BIP44, BIP84 e no Bitcoin Core e, como derivá-las, começando com uma seed ou palavras mnemônicas. + +> :fire: ***Qual é o poder do BIP32?*** As chaves são o elemento mais difícil (e mais perigoso) da maioria das operações criptográficas. Se as perdermos, perderemos tudo o que a chave protegeu. O BIP32 garante que só precisamos conhecer uma chave, a semente, ao invés de um grande número de chaves diferentes para endereços diferentes. + +> :fire: ***Qual é o poder do BIP32 na Libwally?*** O Bitcoind já faz a criação de endereços baseada em HD para nós, o que significa que normalmente não precisamos nos preocupar em derivar endereços dessa maneira. No entanto, usar as funções BIP32 da Libwally pode ser muito útil se estivermos uma máquina offline onde precisamos derivar endereços, possivelmente com base em uma semente passada do `bitcoind` para nosso dispositivo offline (ou vice-versa). + +## O Que Vem Depois? + +Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.4: Usando o PSBTs no Libwally](16_4_Using_PSBTs_in_Libwally.md). \ No newline at end of file diff --git a/pt/16_4_Using_PSBTs_in_Libwally.md b/pt/16_4_Using_PSBTs_in_Libwally.md new file mode 100644 index 0000000..efc9b3b --- /dev/null +++ b/pt/16_4_Using_PSBTs_in_Libwally.md @@ -0,0 +1,378 @@ +# 16.4: Usando o PSBTs na Libwally + +> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. + +Nós aprendemos tudo sobre as transações do Bitcoin parcialmente assinadas (PSBTs) na seção [§7.1](07_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md) e na [§7.2](07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md), e como vimos na [§7.3: Integrando com Hardware Wallets](/github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/07_3_Integrating_with_Hardware_Wallets.md), uma das nossas principais vantagens é a capacidade de integração com nodes offline, como Hardware Wallets. O HWI permitiu que passassemos comandos para uma carteira de hardware, mas o que a própria carteira usa para gerenciar os PSBTs? Por acaso, podemos usar algo na Libwally, como esta seção irá demonstrar. + +Basicamente, a Libwally tem todas as funcionalidades PSBT, então se há algo que podemos fazer com o `bitcoind`, também podemos fazer usando a Libwally, mesmo se nosso dispositivo estiver offline. O que se iremos fazer agora, é a introdução a um tópico bem complexo. + +## Convertendo um PSBT + +Converter um PSBT na estrutura interna da Libwally é incrivelmente fácil, basta executar `wally_psbt_from_base64` com um PSBT base64, que são as saídas produzidas pelo `bitcoin-cli`, como: + +`cHNidP8BAJoCAAAAAri6BLjKQZGO9Y1iVIYbxlxBJ2kqsTPWnxGaH4HrSjxbAAAAAAD+////leV0hwJ0fO40RmhuFVIYtO16ktic2J4vJFLAsT5TM8cBAAAAAP7///8CYOMWAAAAAAAWABTHctb5VULhHvEejvx8emmDCtOKBU+gBwAAAAAAFgAU9Ojd5ds3CJi1fIRWbj92CYhQgX0AAAAAAAEBH0BCDwAAAAAAFgAUABk8i/Je8Fb41FcaHD9lEj5f54giBgMBaNlILisC1wJ/tKie3FStqhrfcJM09kfQobBTOCiuxRiaHVILVAAAgAEAAIAAAACAAAAAADkCAAAAAQEfQEIPAAAAAAAWABQtTxOfqohTBNFWFqFm0tUVdK9KXSIGAqATz5xLX1aJ2SUwNqPkd8+YaJYm94FMlPCScm8Rt0GrGJodUgtUAACAAQAAgAAAAIAAAAAAAAAAAAAAIgID2UK1nupSfXC81nmB65XZ+pYlJp/W6wNk5FLt5ZCSx6kYmh1SC1QAAIABAACAAAAAgAEAAAABAAAAAA==` + +No entanto, é um pouco mais difícil de lidar com o resultado, porque a Libwally o converte em uma estrutura `wally_psbt` muito complexa. + +Here's how it's defined in `/usr/include/wally_psbt.h`: +Veja como é definido no arquivo `/usr/include/wally_psbt.h`: +``` +struct wally_psbt { + unsigned char magic[5]; + struct wally_tx *tx; + struct wally_psbt_input *inputs; + size_t num_inputs; + size_t inputs_allocation_len; + struct wally_psbt_output *outputs; + size_t num_outputs; + size_t outputs_allocation_len; + struct wally_unknowns_map *unknowns; + uint32_t version; +}; + +struct wally_psbt_input { + struct wally_tx *non_witness_utxo; + struct wally_tx_output *witness_utxo; + unsigned char *redeem_script; + size_t redeem_script_len; + unsigned char *witness_script; + size_t witness_script_len; + unsigned char *final_script_sig; + size_t final_script_sig_len; + struct wally_tx_witness_stack *final_witness; + struct wally_keypath_map *keypaths; + struct wally_partial_sigs_map *partial_sigs; + struct wally_unknowns_map *unknowns; + uint32_t sighash_type; +}; + +struct wally_psbt_output { + unsigned char *redeem_script; + size_t redeem_script_len; + unsigned char *witness_script; + size_t witness_script_len; + struct wally_keypath_map *keypaths; + struct wally_unknowns_map *unknowns; +}; +``` +Estes, por sua vez, usam algumas estruturas de transação definidas em `/usr/include/wally_transaction.h`: +``` +struct wally_tx { + uint32_t version; + uint32_t locktime; + struct wally_tx_input *inputs; + size_t num_inputs; + size_t inputs_allocation_len; + struct wally_tx_output *outputs; + size_t num_outputs; + size_t outputs_allocation_len; +}; + +struct wally_tx_output { + uint64_t satoshi; + unsigned char *script; + size_t script_len; + uint8_t features; +}; +``` +Tem muita coisa aí! Embora muito disso deva ser familiar dos capítulos anteriores, é um pouco intimidador ver tudo disposto em estruturas C. + +## Lendo um PSBT convertido + +Obviamente, podemos ler qualquer coisa de uma estrutura PSBT chamando os elementos individuais das várias subestruturas. A seguir, uma breve visão geral que mostra como captar alguns dos elementos. + +Aqui está um exemplo de recuperação dos valores e os `scriptPubKeys` das entradas: +``` + int inputs = psbt->num_inputs; + printf("TOTAL INPUTS: %i\n",inputs); + + for (int i = 0 ; i < inputs ; i++) { + printf("\nINPUT #%i: %i satoshis\n",i, psbt->inputs[i].witness_utxo->satoshi); + + char *script_hex; + wally_hex_from_bytes(psbt->inputs[i].witness_utxo->script,psbt->inputs[i].witness_utxo->script_len,&script_hex); + printf("scriptPubKey: %s\n",script_hex); + wally_free_string(script_hex); + + } +``` +Este padrão de programação será usado em muitas partes do PSBT. Podemos olhar para o tamanho do array de entrada e depois o percorrer, recuperando o que desejamos observar (neste caso, satoshis e scripts). + +Aqui está um exemplo semelhante para as saídas: +``` + int outputs = psbt->num_outputs; + printf("\nTOTAL OUTPUTS: %i\n",outputs); + for (int i = 0 ; i < outputs ; i++) { + + char *pubkey_hex; + wally_hex_from_bytes(psbt->tx->outputs[i].script,psbt->tx->outputs[i].script_len,&pubkey_hex); + printf("\nINPUT #%i\n",i); + printf("scriptPubKey: %s\n",pubkey_hex); + wally_free_string(pubkey_hex); + } +``` +Obviamente, há muito mais coisas que poderemos observar nos PSBTs. Na verdade, olhar é o ponto principal de um PSBT: Podemos verificar entradas e saídas de um computador offline. + +> :warning: **AVISO:** Estas funções de leitura são _muito_ rudimentares e não funcionarão corretamente para situações extremamente normais como uma entrada ou saída que ainda está vazia ou que inclui um `non_witness_utxo`. Eles darão um segfault se não forem entregues um PSBT precisamente esperado. Um verdadeiro leitor precisaria ser consideravelmente mais robusto, para cobrir todas as situações possíveis, mas vamos deixar isso para o leitor. + +### Testando nosso leitor PSBT + +Novamente, o código para este leitor PSBT (extremamente rudimentar e específico) está no [diretório src/](src/16_4_examinepsbt.c). + +Podemos compilá-lo normalmente: +``` +$ cc examinepsbt.c -lwallycore -o examinepsbt +``` +O seguinte PSBT da seção [§7.3](07_3_Integrating_with_Hardware_Wallets.md) pode ser usado para o teste, pois atende aos critérios muito restritos exigidos por esta implementação limitada: +``` +psbt=cHNidP8BAJoCAAAAAri6BLjKQZGO9Y1iVIYbxlxBJ2kqsTPWnxGaH4HrSjxbAAAAAAD+////leV0hwJ0fO40RmhuFVIYtO16ktic2J4vJFLAsT5TM8cBAAAAAP7///8CYOMWAAAAAAAWABTHctb5VULhHvEejvx8emmDCtOKBU+gBwAAAAAAFgAU9Ojd5ds3CJi1fIRWbj92CYhQgX0AAAAAAAEBH0BCDwAAAAAAFgAUABk8i/Je8Fb41FcaHD9lEj5f54giBgMBaNlILisC1wJ/tKie3FStqhrfcJM09kfQobBTOCiuxRiaHVILVAAAgAEAAIAAAACAAAAAADkCAAAAAQEfQEIPAAAAAAAWABQtTxOfqohTBNFWFqFm0tUVdK9KXSIGAqATz5xLX1aJ2SUwNqPkd8+YaJYm94FMlPCScm8Rt0GrGJodUgtUAACAAQAAgAAAAIAAAAAAAAAAAAAAIgID2UK1nupSfXC81nmB65XZ+pYlJp/W6wNk5FLt5ZCSx6kYmh1SC1QAAIABAACAAAAAgAEAAAABAAAAAA== +``` +Ao executar o comando `examinepsbt` com esse PSBT, deveremos ver os scripts nas entradas e saídas: +``` +$ ./examinepsbt $psbt +TOTAL INPUTS: 2 + +INPUT #0: 1000000 satoshis +scriptPubKey: 001400193c8bf25ef056f8d4571a1c3f65123e5fe788 + +INPUT #1: 1000000 satoshis +scriptPubKey: 00142d4f139faa885304d15616a166d2d51574af4a5d + +TOTAL OUTPUTS: 2 + +INPUT #0 +scriptPubKey: 0014c772d6f95542e11ef11e8efc7c7a69830ad38a05 + +INPUT #1 +scriptPubKey: 0014f4e8dde5db370898b57c84566e3f76098850817d +``` +And of course, you can check this with the `decodepsbt` RPC command for `bitcoin-cli`: +E, claro, você pode verificar isso com o comando RPC `decodepsbt` para` bitcoin-cli`: +``` +$ bitcoin-cli decodepsbt $psbt +{ + "tx": { + "txid": "45f996d4ff8c9e9ab162f611c5b6ad752479ede9780f9903bdc80cd96619676d", + "hash": "45f996d4ff8c9e9ab162f611c5b6ad752479ede9780f9903bdc80cd96619676d", + "version": 2, + "size": 154, + "vsize": 154, + "weight": 616, + "locktime": 0, + "vin": [ + { + "txid": "5b3c4aeb811f9a119fd633b12a6927415cc61b8654628df58e9141cab804bab8", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967294 + }, + { + "txid": "c733533eb1c052242f9ed89cd8927aedb41852156e684634ee7c74028774e595", + "vout": 1, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967294 + } + ], + "vout": [ + { + "value": 0.01500000, + "n": 0, + "scriptPubKey": { + "asm": "0 c772d6f95542e11ef11e8efc7c7a69830ad38a05", + "hex": "0014c772d6f95542e11ef11e8efc7c7a69830ad38a05", + "reqSigs": 1, + "type": "witness_v0_keyhash", + "addresses": [ + "tb1qcaedd724gts3aug73m78c7nfsv9d8zs9q6h2kd" + ] + } + }, + { + "value": 0.00499791, + "n": 1, + "scriptPubKey": { + "asm": "0 f4e8dde5db370898b57c84566e3f76098850817d", + "hex": "0014f4e8dde5db370898b57c84566e3f76098850817d", + "reqSigs": 1, + "type": "witness_v0_keyhash", + "addresses": [ + "tb1q7n5dmewmxuyf3dtus3txu0mkpxy9pqtacuprak" + ] + } + } + ] + }, + "unknown": { + }, + "inputs": [ + { + "witness_utxo": { + "amount": 0.01000000, + "scriptPubKey": { + "asm": "0 00193c8bf25ef056f8d4571a1c3f65123e5fe788", + "hex": "001400193c8bf25ef056f8d4571a1c3f65123e5fe788", + "type": "witness_v0_keyhash", + "address": "tb1qqqvnezljtmc9d7x52udpc0m9zgl9leugd2ur7y" + } + }, + "bip32_derivs": [ + { + "pubkey": "030168d9482e2b02d7027fb4a89edc54adaa1adf709334f647d0a1b0533828aec5", + "master_fingerprint": "9a1d520b", + "path": "m/84'/1'/0'/0/569" + } + ] + }, + { + "witness_utxo": { + "amount": 0.01000000, + "scriptPubKey": { + "asm": "0 2d4f139faa885304d15616a166d2d51574af4a5d", + "hex": "00142d4f139faa885304d15616a166d2d51574af4a5d", + "type": "witness_v0_keyhash", + "address": "tb1q948388a23pfsf52kz6skd5k4z4627jja2evztr" + } + }, + "bip32_derivs": [ + { + "pubkey": "02a013cf9c4b5f5689d9253036a3e477cf98689626f7814c94f092726f11b741ab", + "master_fingerprint": "9a1d520b", + "path": "m/84'/1'/0'/0/0" + } + ] + } + ], + "outputs": [ + { + }, + { + "bip32_derivs": [ + { + "pubkey": "03d942b59eea527d70bcd67981eb95d9fa9625269fd6eb0364e452ede59092c7a9", + "master_fingerprint": "9a1d520b", + "path": "m/84'/1'/0'/1/1" + } + ] + } + ], + "fee": 0.00000209 +} +``` +Podemos ver a entrada de satoshis e o `scriptPubKey` claramente listadas nos `inputs` e a nova `scriptPubKey` no `vout` do `tx`. + +Então, está tudo lá para utilizarmos! + +## Criando um PSBT + +Conforme observado no início desta seção, todas as funções necessárias para criar e processar os PSBTs estão disponíveis em Libwally. Na verdade, percorrer todo o processo para fazer isso é complexo o suficiente para estar além do escopo desta seção, mas aqui está um resumo rápido das funções necessárias. Observe que a [documentação](https://wally.readthedocs.io/en/latest/psbt/) está desatualizada para os PSBTs, portanto, precisaremos consultar o `/usr/include/wally_psbt.h` para obter as informações completas. + +Conforme discutido na seção [§7.1](07_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md), existem várias funções envolvidas na criação dos PSBTs. + +### Assumindo o papel de criador + +A função de criador tem a tarefa de criar um PSBT com pelo menos uma entrada. + +Um PSBT é criado com um simples uso do comando `wally_psbt_init_alloc`, informando quantas entradas e saídas eventualmente adicionaremos: +``` + struct wally_psbt *psbt; + lw_response = wally_psbt_init_alloc(0,1,1,0,&psbt); +``` +Mas o que temos ainda não é um PSBT legal, por falta de entradas. Podemos criá-las criando uma transação e definindo-a como a transação global no PSBT, que atualiza todas as entradas e saídas: +``` + struct wally_tx *gtx; + lw_response = wally_tx_init_alloc(0,0,1,1,>x); + lw_response = wally_psbt_set_global_tx(psbt,gtx); +``` +### Testando nosso PSBT criado + +Neste ponto, devemos ter um PSBT vazio, mas funcionando, que pode ser visto compilando e executando [o programa](src/16_4_createemptypsbt.c). +``` +$ cc createemptypsbt.c -lwallycore -o createemptypsbt +$ ./createemptypsbt +cHNidP8BAAoAAAAAAAAAAAAAAA== +``` +Podemos até usar o `bitcoin-cli` para testar o resultado: +``` +$ psbt=$(./createpsbt) +$ bitcoin-cli decodepsbt $psbt +{ + "tx": { + "txid": "f702453dd03b0f055e5437d76128141803984fb10acb85fc3b2184fae2f3fa78", + "hash": "f702453dd03b0f055e5437d76128141803984fb10acb85fc3b2184fae2f3fa78", + "version": 0, + "size": 10, + "vsize": 10, + "weight": 40, + "locktime": 0, + "vin": [ + ], + "vout": [ + ] + }, + "unknown": { + }, + "inputs": [ + ], + "outputs": [ + ], + "fee": 0.00000000 +} +``` +## Assumindo as demais das funções + +Assim como na leitura de PSBT, estamos introduzindo o conceito de criação do PSBT e, em seguida, deixando o resto como um exercício para o leitor. + +A seguir está uma lista aproximada de funções para cada papel. Mais funções serão necessárias para criar alguns dos elementos que são adicionados aos PSBTs. + +**Criador:** + +* wally_psbt_init_alloc +* wally_psbt_set_global_tx + +**Atualizador:** + +* wally_psbt_input_set_non_witness_utxo +* wally_psbt_input_set_witness_utxo +* wally_psbt_input_set_redeem_script +* wally_psbt_input_set_witness_script +* wally_psbt_input_set_keypaths +* wally_psbt_input_set_unknowns +* wally_psbt_output_set_redeem_script +* wally_psbt_output_set_witness_script +* wally_psbt_output_set_keypaths +* wally_psbt_output_set_unknowns + +**Assinante:** + +* wally_psbt_input_set_partial_sigs +* wally_psbt_input_set_sighash_type +* wally_psbt_sign + +**Combinador:** + +* wally_psbt_combine + +**Finalizador:** +* wally_psbt_finalize +* wally_psbt_input_set_final_script_sig +* wally_psbt_input_set_final_witness + +**Extrator:** + +* wally_psbt_extract + +## Resumo: Usando o PSBTs na Libwally + +Esta seção poderia ser um capítulo inteiro, já que trabalhar com os PSBTs em um nível baixo é um trabalho muito intenso que requer uma manipulação muito mais intensiva de entradas e saídas como foi o caso do [Capítulo 7](07_0_Expanding_Bitcoin_Transactions_PSBTs.md). Ao invés disso, esta seção mostra o básico: como extrair informações de um PSBT e como começar a criar um. + +> :fire: ***Qual é o poder dos PSBTs na Libwally?*** Obviamente, já podemos fazer tudo isso nos `bitcoin-cli`, e é mais simples porque o Bitcoin Core gerencia muito do penoso trabalho. A vantagem de usar o Libwally é que ele pode ser executado offline, então pode ser a Libwally que está do outro lado de um dispositivo de hardware com o qual nosso `bitcoin-cli` está se comunicando com o HWI. Este é, de fato, um dos principais pontos dos PSBTs: ser capaz de manipular transações parcialmente assinadas sem a necessidade de um node completo. A Libwally permite isso. + +## O Que Vem Depois? + +Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.5: Usando Scripts no Libwally](16_5_Using_Scripts_in_Libwally.md). \ No newline at end of file diff --git a/pt/16_5_Using_Scripts_in_Libwally.md b/pt/16_5_Using_Scripts_in_Libwally.md new file mode 100644 index 0000000..5afb79e --- /dev/null +++ b/pt/16_5_Using_Scripts_in_Libwally.md @@ -0,0 +1,179 @@ +# 16.5: Usando Scripts na Libwally + +> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. + +Na seção 3 deste capítulo, ao apresentar os scripts, dissemos que era provável que criássemos transações usando scripts com uma API e dissemos que este era um tópico para o futuro. Bem, o futuro já chegou. + +## Criando o Script + +Criar o script é a coisa mais _fácil_ de se fazer na Libwally. Veja o exemplo a seguir, um simples [Puzzle Script](13_1_Writing_Puzzle_Scripts.md) ao qual retornamos de vez em quando: +``` +OP_ADD 99 OP_EQUAL +``` +Usando o `btcc`, podemos serializar isso. +``` +$ btcc OP_ADD 99 OP_EQUAL +warning: ambiguous input 99 is interpreted as a numeric value; use 0x99 to force into hexadecimal interpretation +93016387 +``` +Anteriormente, construímos o script P2SH padrão manualmente, mas a Libwally pode fazer isso por nós. + +Primeiro, a Libwally precisa converter o hex em bytes, uma vez que os bytes são o que realmente funciona: +``` + int script_length = strlen(script)/2; + unsigned char bscript[script_length]; + + lw_response = wally_hex_to_bytes(script,bscript,script_length,&written); +``` +Então, executamos o comando `wally_scriptpubkey_p2sh_from_bytes` com os bytes, dizendo a Libwally para também fazer o `HASH160` para nós: +``` + unsigned char p2sh[WALLY_SCRIPTPUBKEY_P2SH_LEN]; + + lw_response = wally_scriptpubkey_p2sh_from_bytes(bscript,sizeof(bscript),WALLY_SCRIPT_HASH160,p2sh,WALLY_SCRIPTPUBKEY_P2SH_LEN,&written); +``` +Se olharmos os resultados do `p2sh`, veremos o seguinte: +``` +a9143f58b4f7b14847a9083694b9b3b52a4cea2569ed87 +``` +Que [devemos nos lembrar](10_2_Building_the_Structure_of_P2SH.md) de divide em: +``` +a9 / 14 / 3f58b4f7b14847a9083694b9b3b52a4cea2569ed / 87 +``` +Esse é nosso velho amigo `OP_HASH160 3f58b4f7b14847a9083694b9b3b52a4cea2569ed OP_EQUAL`. + +Basicamente, a Libwally pegou nosso script de resgate serializado, fez o hash para nós com SHA-256 e RIPEMD-160 e aplicou o enquadramento padrão para transformá-lo em um P2SH adequado. Fizemos um trabalho semelhante ao feito na seção [§10.2](10_2_Building_the_Structure_of_P2SH.md), mas com um excesso de comandos shell. + +Na verdade, podemos verificar novamente o nosso trabalho usando os mesmos comandos do §10.2: +``` +$ redeemScript="93016387" +$ echo -n $redeemScript | xxd -r -p | openssl dgst -sha256 -binary | openssl dgst -rmd160 +(stdin)= 3f58b4f7b14847a9083694b9b3b52a4cea2569ed +``` + +## Criando uma transação + +A fim de fazer uso do `pubScriptKey` que acabamos de criar, precisamos criar uma transação e incorporar o `pubScriptKey` dentro, e esta é a grande mudança para o `bitcoin-cli`. Podemos criar manualmente uma transação com um script P2SH. + +O processo de criação de uma transação na Libwally é muito intenso, assim como o processo de criação de um PSBT, portanto, vamos apenas esboçá-lo, pegando um atalho e, em seguida, deixando um método sem atalhos para investigação futura. + +Criar uma transação em si é fácil, só precisamos dizer ao comando `wally_tx_init_alloc` nosso número de versão, o tempo de bloqueio e o número de entradas e saídas: +``` + struct wally_tx *tx; + lw_response = wally_tx_init_alloc(2,0,1,1,&tx); +``` +Preencher essas entradas e saídas é onde as coisas ficam complicadas! + +### Criando uma saída na transação + +Para criar uma saída, dizemos a `wally_tx_output_init_alloc` quantos satoshis estamos gastando, além de entregar o script de bloqueio: +``` + struct wally_tx_output *tx_output; + lw_response = wally_tx_output_init_alloc(95000,p2sh,sizeof(p2sh),&tx_output); +``` +Essa parte não foi nem um pouco difícil e nos permitiu que finalmente incorporássemos um P2SH em um `vout`. + +Mais um comando o adiciona à nossa transação: +``` + lw_response = wally_tx_add_output(tx,tx_output); +``` + +### Criando uma entrada na transação + +Criar a entrada é muito mais difícil porque temos que empilhar informações nas rotinas de criação, nem todas as quais são intuitivamente acessíveis quando usamos a Libwally. Então, ao invés de ir mergulhar fundo nessa biblioteca, é neste momento que pegamos nosso atalho. Escrevemos o código de forma que seja passado o código hexadecimal para uma transação que já foi criada e, em seguida, apenas reutilizamos a entrada. + +A conversão do código hexadecimal é feita com `wally_tx_from_hex`: +``` + struct wally_tx *utxo; + lw_response = wally_tx_from_hex(utxo_hex,0,&utxo); +``` +Então podemos roubar as entradas de nosso código hexadecimal para criar uma entrada com a Libwally: +``` + struct wally_tx_input *tx_input; + lw_response = wally_tx_input_init_alloc(utxo->inputs[0].txhash,sizeof(utxo->inputs[0].txhash),utxo->inputs[0].index,0,utxo->inputs[0].script,utxo->inputs[0].script_len,utxo->inputs[0].witness,&tx_input); + assert(lw_response == WALLY_OK); +``` +Como seria de esperar, adicionamos essa entrada à nossa transação: +``` + lw_response = wally_tx_add_input(tx,tx_input); +``` + +> **NOTA:** Obviamente, iremos querer criar nossas próprias entradas se estivermos usando Libwally aplicativos reais, mas isso é uma primeira etapa. E, na verdade, pode ser útil para integração com o `bitcoin-cli`, como veremos na seção [§16.7](16_7_Integrating_Libwally_and_Bitcoin-CLI.md). + +### Mostrando na tela uma transação + +Teoricamente, poderíamos assinar e enviar esta transação para nosso programa C construído na Libwally, mas mantendo a ideia de que estamos apenas usando um programa C simples para substituir um P2SH, vamos imprimir o novo hex. Isso é feito com a ajuda de `wally_tx_to_hex`: +``` + char *tx_hex; + lw_response = wally_tx_to_hex(tx,0, &tx_hex); + + printf("%s\n",tx_hex); +``` +Mostraremos como fazer uso disso na seção §16.7. + +## Testando nosso script de substituição + +Podemos pegar o código de teste do [diretório src/](src/16_5_replacewithscript.c) e compilá-lo: +``` +$ cc replacewithscript.c -lwallycore -o replacewithscript +``` +Depois, preparamos uma transação hexadecimal e um script hexadecimal serializado: +``` +hex=020000000001019527cebb072524a7961b1ba1e58fc18dd7c6fc58cd6c1c45d7e1d8fc690b006e0000000017160014cc6e8522f0287b87b7d0a83629049c2f2b0e972dfeffffff026f8460000000000017a914ba421212a629a840492acb2324b497ab95da7d1e87306f0100000000001976a914a2a68c5f9b8e25fdd1213c38d952ab2be2e271be88ac02463043021f757054fa61cfb75b64b17230b041b6d73f25ff9c018457cf95c9490d173fb4022075970f786f24502290e8a5ed0f0a85a9a6776d3730287935fb23aa817791c01701210293fef93f52e6ce8be581db62229baf116714fcb24419042ffccc762acc958294e6921b00 + +script=93016387 +``` +Podemos então executar o programa de substituição: +``` +$ ./replacewithscript $hex $script +02000000019527cebb072524a7961b1ba1e58fc18dd7c6fc58cd6c1c45d7e1d8fc690b006e0000000017160014cc6e8522f0287b87b7d0a83629049c2f2b0e972d0000000001187301000000000017a9143f58b4f7b14847a9083694b9b3b52a4cea2569ed8700000000 +``` +Podemos ver os resultados com o `bitcoin-cli`: +``` +$ bitcoin-cli decoderawtransaction $newhex +{ + "txid": "f4e7dbab45e759a7ac6e2fb0f10720cd29d047efad89fe1b569f5f4ba61fd8e6", + "hash": "f4e7dbab45e759a7ac6e2fb0f10720cd29d047efad89fe1b569f5f4ba61fd8e6", + "version": 2, + "size": 106, + "vsize": 106, + "weight": 424, + "locktime": 0, + "vin": [ + { + "txid": "6e000b69fcd8e1d7451c6ccd58fcc6d78dc18fe5a11b1b96a7242507bbce2795", + "vout": 0, + "scriptSig": { + "asm": "0014cc6e8522f0287b87b7d0a83629049c2f2b0e972d", + "hex": "160014cc6e8522f0287b87b7d0a83629049c2f2b0e972d" + }, + "sequence": 0 + } + ], + "vout": [ + { + "value": 0.00095000, + "n": 0, + "scriptPubKey": { + "asm": "OP_HASH160 3f58b4f7b14847a9083694b9b3b52a4cea2569ed OP_EQUAL", + "hex": "a9143f58b4f7b14847a9083694b9b3b52a4cea2569ed87", + "reqSigs": 1, + "type": "scripthash", + "addresses": [ + "2My2ApqGcoNXYceZC4d7fipBu4GodkbefHD" + ] + } + } + ] +} +``` +O `vin` deve apenas corresponder à entrada que substituímos, mas é o `vout` que é empolgante. Criamos uma transação com um `scripthash`! + +## Resumo: Usando Scripts na Libwally + +A criação de transações na Libwally é outro tópico que pode ocupar um capítulo inteiro, mas o melhor é que, uma vez que demos esse salto, pode introduzir um P2SH `scriptPubKey`, e só essa parte é muito fácil. Embora a metodologia detalhada neste capítulo exija que já tenhamos um hex de transação em mãos (provavelmente criado com o `bitcoin-cli`) se nos aprofundarmos na Libwally, podemos fazer tudo sozinho. + +> :fire: ***Qual é o poder dos scripts no Libwally?*** De maneira bem simples, podemos fazer algo que não podíamos antes. Criar uma transação bloqueada com um P2SH arbitrário. + +## O Que Vem Depois? + +Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.6: Usando Outras Funções no Libwally](16_6_Using_Other_Functions_in_Libwally.md). \ No newline at end of file diff --git a/pt/16_6_Using_Other_Functions_in_Libwally.md b/pt/16_6_Using_Other_Functions_in_Libwally.md new file mode 100644 index 0000000..f198be2 --- /dev/null +++ b/pt/16_6_Using_Other_Functions_in_Libwally.md @@ -0,0 +1,126 @@ +# 16.6: Usando Outras Funções no Libwally + +> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. + +A Libwally é uma extensa biblioteca que fornece uma quantidade considerável de funcionalidades relacionadas à carteira, muitas delas não disponíveis por meio do `bitcoin-cli`. A seguir, está uma visão geral de algumas funcionalidades não abordadas anteriormente neste capítulo. + +## Usando funções criptográficas + +Diversas funções criptográficas podem ser acessadas diretamente na Libwally: + + * `wally_aes` - Usa criptografia ou descriptografia AES; + * `wally_aes_cbc` - Usa criptografia ou descriptografia AES no modo CBC; + * `wally_hash160` - Usa hash RIPEMD-160 (SHA-256); + * `wally_scrypt` - Usa derivação de chave Scrypt; + * `wally_sha256` - Usa hash SHA256; + * `wally_sha256_midstate` - Usa SHA256 para fazer hash apenas do primeiro bloco de dados; + * `wally_sha256d` - Conduza um hash duplo SHA256; + * `wally_sha512` - Usa hash SHA512. + +Existem também funções HMAC para os dois hashes SHA, que são usados ​​para gerar códigos de autenticação de mensagem com base nos hashes. Eles são usados no [BIP32](https://en.bitcoin.it/wiki/BIP_0032), entre outros lugares. + + * `wally_hmac_sha256` + * `wally_hmac_sha512` + +Funções adicionais cobrem derivação chave PBKDF2 e matemática de curva elíptica. + +## Usando funções de endereço + +A Libwally contém várias funções que podem ser usadas para importar, exportar e traduzir endereços de Bitcoin. + +Alguns convertem entre endereços e bytes `scriptPubKey`: + + * `wally_addr_segwit_from_bytes` - Converta um programa witness (em bytes) em um endereço Segwit; + * `wally_addr_segwit_to_bytes` - Converta um endereço Segwit em um `scriptPubKey` (em bytes); + * `wally_address_to_scriptpubkey` - Converta um endereço legado em um `scriptPubKey` (em bytes); + * `wally_scriptpubkey_to_address` - Converta um `scriptPubKey` (em bytes) em um endereço legado. + +Alguns estão relacionados ao formato de importação de carteira (WIF): + + * `wally_wif_from_bytes` - Converta uma chave privada (em bytes) para um WIF; + * `wally_wif_is_uncompressed` - Determina se um WIF está descompactado; + * `wally_wif_to_address` - Deriva um endereço P2PKH de um WIF; + * `wally_wif_to_bytes` - Converta um WIF em uma chave privada (em bytes); + * `wally_wif_to_public_key` - Deriva uma chave pública (em bytes) de um WIF. + +## Usando funções BIP32 + +Existem funções adicionais de carteira HD BIP32, além do que foi abordado na seção [§16.3: Usando o BIP32 no Libwally](16_3_Using_BIP32_in_Libwally.md). + + * `bip32_key_get_fingerprint` - Gera uma impressão digital BIP32 para uma chave estendida; + * `bip32_key_serialize` - Transforma uma chave estendida em bytes serializados; + * `bip32_key_strip_private_key` - Converte uma chave privada estendida em uma chave pública estendida; + * `bip32_key_unserialize` - Transforma bytes serializados em uma chave estendida. + +Existem também vários outros comandos, dependendo se desejamos alocar memória ou fazer com que a Libwally faça o `_alloc` para nós. + +## Usando funções BIP38 + +O [BIP38](https://github.com/bitcoin/bips/blob/master/bip-0038.mediawiki) permite a criação de uma chave privada protegida por senha. Não ensinamos porque consideramos perigoso inserir esse tipo de fator humano no gerenciamento de chaves. Se duvida disso, consulte [#SmartCustody](https://www.smartcustody.com/index.html). + +As principais funções são: + + * `bip38_from_private_key` - Codifica uma chave privada usando BIP38; + * `bip38_to_private_key` - Decodifica uma chave privada usando BIP38. + +## Usando funções BIP39 + +Algumas funções de palavras mnemônicas do BIP39 foram resumidas recentemente na seção [§16.2: Usando o BIP39 no Libwally](16_2_Using_BIP39_in_Libwally.md): + + * `bip39_get_languages` - Veja a lista de idiomas suportados; + * `bit39_get_word` - Recupera uma palavra específica da lista de palavras de um idioma; + * `bip39_get_wordlist` - Veja uma lista de palavras para um idioma. + +## Usando funções PSBT + +As listas da maioria das funções PSBT podem ser encontradas na seção [16.4: Usando o PSBTs no Libwally](16_4_Using_PSBTs_in_Libwally.md). + +## Usando funções de script + +A seção [§16.5: Usando Scripts no Libwally](16_5_Using_Scripts_in_Libwally.md) apenas tocou nas funções de scripts da Libwally. + +Há outra função que permite determinar o tipo de script encontrado em uma transação: + + * `wally_scriptpubkey_get_type` — Determina a transaction's script type; + * `wally_scriptpubkey_get_type` - Determina o tipo de script de uma transação. + +Depois, há uma série de funções que criam `scriptPubKey` a partir de bytes, o `scriptSig` a partir de assinaturas e witness a partir de bytes ou assinaturas. + + * `wally_script_push_from_bytes` + * `wally_scriptpubkey_csv_2of2_then_1_from_bytes` + * `wally_scriptpubkey_csv_2of3_then_2_from_bytes` + * `wally_scriptpubkey_multisig_from_bytes` + * `wally_scriptpubkey_op_return_from_bytes` + * `wally_scriptpubkey_p2pkh_from_bytes` + * `wally_scriptpubkey_p2sh_from_bytes` + * `wally_scriptsig_multisig_from_bytes` + * `wally_scriptsig_p2pkh_from_der` + * `wally_scriptsig_p2pkh_from_sig` + * `wally_witness_multisig_from_bytes` + * `wally_witness_p2wpkh_from_der` + * `wally_witness_p2wpkh_from_sig` + * `wally_witness_program_from_bytes` + +## Usando Funções de Transação + +Também mal tocamos nas funções que podem ser usadas para criar e converter funções na seção [§16.5](16_5_Using_Scripts_in_Libwally.md). + +Existem inúmeras funções informativas, algumas das mais interessantes são: + + * `wally_tx_get_length` + * `wally_tx_get_total_output_satoshi` + * `wally_tx_get_weight` + +Também existem funções que afetam um `wally_tx`, um `wally_tx_input`, um `wally_tx_output`, ou um `wally_tx_witness_stack` e que criam assinaturas. + +## Usando funções de elementos + +A Libwally pode ser compilada para ser usada com os Elementos do Blockstream, que inclui acesso às funções dos ativos. + +## Resumo: Usando Outras Funções no Libwally + +Há muito mais coisas que podemos fazer com a Libwally, mais do que podemos abordar neste capítulo ou mesmo listar nesta seção. Notavelmente, podemos executar funções criptográficas, codificar chaves privadas, criar transações completas e usar elementos. A [documentação da Libwally](https://wally.readthedocs.io/en/latest/) é o lugar onde podemos obter mais informações, embora, no momento da criação deste livro, a documentação esteja limitada e desatualizada. Os arquivos de cabeçalho da Libwally são um backup se os documentos estiverem incompletos ou incorretos. + +## O Que Vem Depois? + +Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.7: Integrando o Libwally ao Bitcoin-CLI](16_7_Integrating_Libwally_and_Bitcoin-CLI.md). \ No newline at end of file diff --git a/pt/16_7_Integrating_Libwally_and_Bitcoin-CLI.md b/pt/16_7_Integrating_Libwally_and_Bitcoin-CLI.md new file mode 100644 index 0000000..b93d537 --- /dev/null +++ b/pt/16_7_Integrating_Libwally_and_Bitcoin-CLI.md @@ -0,0 +1,330 @@ +# 16.7: Integrando o Libwally ao Bitcoin-CLI + +> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. + +A Libwally é limitado. Trata-se de manipular seeds, chaves, endereços e outros elementos de carteiras, com algumas funções adicionais relacionadas a transações e PSBTs que podem ser úteis para serviços que não estão conectados a nodes completos na Internet. No final das contas, no entanto, precisaremos de serviços de nodes completos para aproveitar as vantagens da Libwally. + +Esta última seção oferecerá alguns exemplos de uso de programas Libwally para complementar um ambiente `bitcoin-cli`. Embora esses exemplos impliquem que esses serviços estão todos na mesma máquina, eles podem se tornar ainda mais poderosos se o serviço `bitcoin-cli` estiver diretamente conectado à internet e o serviço Libwally não. + +## Compartilhando uma transação + +Na seção [§16.5: Usando Scripts no Libwally](16_5_Using_Scripts_in_Libwally.md) detalhamos como a Libwally poderia ser usada para reescrever uma transação existente, para fazer algo que o `bitcoin-cli` não pode, ou seja, produzir uma transação que contém um P2SH único. Obviamente, este é um bloco de construção, se decidirmos nos aprofundar no Libwally, criaremos transações inteiras por conta própria. Mas, esta metodologia abreviada também tem seu próprio uso, mostrar como as transações podem ser passadas de um lado para outro entre `bitcoin-cli` e Libwally, demonstrando um primeiro exemplo de como usá-los de forma complementar. + +Para demonstrar totalmente essa metodologia, criaremos uma transação com o `bitcoin-cli`, usando este UTXO: +``` + { + "txid": "c0a110a7a84399b98052c6545018873b13ee3128fa74f7a697779174a36ea33a", + "vout": 1, + "address": "mvLyH7Rs45c16FG2dfV7uuTKV6pL92kWxo", + "label": "", + "scriptPubKey": "76a914a2a68c5f9b8e25fdd1213c38d952ab2be2e271be88ac", + "amount": 0.00094000, + "confirmations": 17375, + "spendable": true, + "solvable": true, + "desc": "pkh([ce0c7e14/0'/0'/5']0368d0fffa651783524f8b934d24d03b32bf8ff2c0808943a556b3d74b2e5c7d65)#qldtsl65", + "safe": true + } +``` +Agora, já sabemos como configurar uma transação com o `bitcoin-cli`: +``` +$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[0] | .txid') +$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[0] | .vout') +$ recipient=tb1qycsmq3jas5wkhf8xrfn8k7438cm5pc8h9ae2k0 +$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.0009 }''') +``` +Embora tenhamos colocado um destinatário e uma quantia na saída, é irrelevante, porque nós o reescreveremos. Um código mais elaborado poderia ler as informações `vout` existentes antes de reescrever, mas estamos mantendo as coisas muito próximas do nosso [código original](src/16_5_replacewithscript.c). + +Aqui está a única alteração necessária, para permitir que especifiquemos os satoshis no `vout`, sem ter que codificá-lo, como no original: +``` +... + int satoshis = atoi(argv[3]); +... + lw_response = wally_tx_output_init_alloc(satoshis,p2sh,sizeof(p2sh),&tx_output); +... +``` +Então executamos as coisas como antes: +``` +$ newtxhex=$(./replacewithscript $rawtxhex $script 9000) +``` +Esta é a aparência da transação original: +``` +$ bitcoin-cli decoderawtransaction $rawtxhex +{ + "txid": "438d50edd7abeaf656c5abe856a00a20af5ff08939df8fdb9f8bfbfb96234fcb", + "hash": "438d50edd7abeaf656c5abe856a00a20af5ff08939df8fdb9f8bfbfb96234fcb", + "version": 2, + "size": 82, + "vsize": 82, + "weight": 328, + "locktime": 0, + "vin": [ + { + "txid": "c0a110a7a84399b98052c6545018873b13ee3128fa74f7a697779174a36ea33a", + "vout": 1, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.00090000, + "n": 0, + "scriptPubKey": { + "asm": "0 2621b0465d851d6ba4e61a667b7ab13e3740e0f7", + "hex": "00142621b0465d851d6ba4e61a667b7ab13e3740e0f7", + "reqSigs": 1, + "type": "witness_v0_keyhash", + "addresses": [ + "tb1qycsmq3jas5wkhf8xrfn8k7438cm5pc8h9ae2k0" + ] + } + } + ] +} +``` +E aqui está a transação reescrita pela Libwally para usar em um P2SH: +``` +standup@btctest:~/c$ bitcoin-cli decoderawtransaction $newtxhex +{ + "txid": "badb57622ab5fe029fc1a71ace9f7b76c695f933bceb0d38a155c2e5c984f4e9", + "hash": "badb57622ab5fe029fc1a71ace9f7b76c695f933bceb0d38a155c2e5c984f4e9", + "version": 2, + "size": 83, + "vsize": 83, + "weight": 332, + "locktime": 0, + "vin": [ + { + "txid": "c0a110a7a84399b98052c6545018873b13ee3128fa74f7a697779174a36ea33a", + "vout": 1, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 0 + } + ], + "vout": [ + { + "value": 0.00090000, + "n": 0, + "scriptPubKey": { + "asm": "OP_HASH160 3f58b4f7b14847a9083694b9b3b52a4cea2569ed OP_EQUAL", + "hex": "a9143f58b4f7b14847a9083694b9b3b52a4cea2569ed87", + "reqSigs": 1, + "type": "scripthash", + "addresses": [ + "2My2ApqGcoNXYceZC4d7fipBu4GodkbefHD" + ] + } + } + ] +} +``` +Depois, podemos assiná-la normalmente com o `bitcoin-cli`: +``` +$ signedtx=$(bitcoin-cli signrawtransactionwithwallet $newtxhex | jq -r '.hex') +``` +E como podemos ver, o resultado é uma transação legítima pronta para ir para a rede Bitcoin: +``` +$ bitcoin-cli decoderawtransaction $signedtx +{ + "txid": "3061ca8c01d029c0086adbf8b7d4280280c8aee151500bab7c4f783bbc8e75e6", + "hash": "3061ca8c01d029c0086adbf8b7d4280280c8aee151500bab7c4f783bbc8e75e6", + "version": 2, + "size": 189, + "vsize": 189, + "weight": 756, + "locktime": 0, + "vin": [ + { + "txid": "c0a110a7a84399b98052c6545018873b13ee3128fa74f7a697779174a36ea33a", + "vout": 1, + "scriptSig": { + "asm": "3044022026c81b6ff4a15135d10c7f4b1ae6e44ac4fdb25c4a3c03161b17b8ab8d04850502200b448d070f418de1ca07e76943d23d447bc95c7c5e0322bcc153cadb5d9befe0[ALL] 0368d0fffa651783524f8b934d24d03b32bf8ff2c0808943a556b3d74b2e5c7d65", + "hex": "473044022026c81b6ff4a15135d10c7f4b1ae6e44ac4fdb25c4a3c03161b17b8ab8d04850502200b448d070f418de1ca07e76943d23d447bc95c7c5e0322bcc153cadb5d9befe001210368d0fffa651783524f8b934d24d03b32bf8ff2c0808943a556b3d74b2e5c7d65" + }, + "sequence": 0 + } + ], + "vout": [ + { + "value": 0.00090000, + "n": 0, + "scriptPubKey": { + "asm": "OP_HASH160 3f58b4f7b14847a9083694b9b3b52a4cea2569ed OP_EQUAL", + "hex": "a9143f58b4f7b14847a9083694b9b3b52a4cea2569ed87", + "reqSigs": 1, + "type": "scripthash", + "addresses": [ + "2My2ApqGcoNXYceZC4d7fipBu4GodkbefHD" + ] + } + } + ] +} +``` +Pronto! Esse é o poder da Libwally com o `bitcoin-cli`. + +Obviamente, também pode passar um PSBT usando as funções descritas na seção [§16.4](16_4_Using_PSBTs_in_Libwally.md) e essa é uma metodologia mais atualizada para o uso moderno do Bitcoin, mas em qualquer um dos exemplos, o conceito de passar transações do `bitcoin-cli` para código Libwally e vice-versa deve ser semelhante. + +## Importando e exportando seeds BIP39 + +Infelizmente, nem todas as interações entre a Libwally e o `bitcoin-cli` são fáceis. Por exemplo, seria bom se pudessemos exportar uma seed HD do `bitcoin-cli`, para gerar a frase mnemônica com a Libwally, ou gerar uma seed de uma frase mnemônica usando a Libwally e depois importá-la para o `bitcoin-cli `. Infelizmente, nada disso é possível neste momento. Uma frase mneômica é traduzida em uma seed usando HMAC-SHA512, o que significa que o resultado é 512 bits. No entanto, o `bitcoin-cli` exporta seeds HD (usando `dumpwallet`) e importa sementes HD (usando `sethdseed`) com um comprimento de 256 bits. Até que isso seja mudado, não podemos fazer nada sobre isso. + +> :book: ***Qual é a diferença entre entropia e uma seed?*** A Libwally diz que criamos nossas frases mnemônicas a partir da entropia. Isso é essencialmente a mesma coisa que uma seed, pois ambos são números grandes e aleatórios. Portanto, se o `bitcoin-cli` fosse compatível com as sementes de frase mnemônica de 512 bits, poderíamos usar uma para gerar as frases mnemônicas e obter os resultados esperados. + +> :book: ***Qual é a diferença entre entropia e entropia bruta?*** Nem toda entropia é a mesma. Quando inserimos entropia em um comando que cria uma seed mnemônica, ela tem um comprimento específico e bem conhecido. Mudar a entropia bruta em uma entropia requer alterar a entropia bruta até que tenha o comprimento e o formato corretos, e nesse ponto podemos reutilizar essa entropia (não bruta) para sempre recriar os mesmos mnemônicos (razão pela qual a entropia é efetivamente a mesma coisa que um seed naquele ponto, mas a entropia bruta não). + +## Importando chaves privadas + +Felizmente, podemos fazer quase a mesma coisa importando uma chave privada gerada na Libwally. Dê uma olhada no [genhd-for-import.c](src/16_7_genhd_for_import.c), uma versão simplificada do programa `genhd` da seção [§16.3](16_3_Using_BIP32_in_Libwally.md) que também usa a biblioteca `jansson` da seção [ §15.1](15_1_Accessing_Bitcoind_with_C.md) para saída regularizada. + +O código atualizado também contém uma alteração importante, pois ele solicita uma impressão digital da Libwally para que possa criar um caminho de derivação de maneira adequada: +``` + char account_fingerprint[BIP32_KEY_FINGERPRINT_LEN]; + lw_response = bip32_key_get_fingerprint(key_account,account_fingerprint,BIP32_KEY_FINGERPRINT_LEN); + + char *fp_hex; + lw_response = wally_hex_from_bytes(account_fingerprint,BIP32_KEY_FINGERPRINT_LEN,&fp_hex); +``` + +> :aviso: **AVISO:** Lembre-se de que a impressão digital nos caminhos de derivação é arbitrária. Como o Libwally fornece um, nós o estamos usando, mas se não tivermos um, poderemos adicionar um código hexadecimal arbitrário de 4 bytes como uma impressão digital em nosso caminho de derivação. + +Certifique-se de compilar o novo código com a biblioteca `jansson`, após instalá-lo (se necessário) de acordo com a seção [§15.1](15_1_Accessing_Bitcoind_with_C.md). +``` +$ cc genhd-for-import.c -lwallycore -lsodium -ljansson -o genhd-for-import +``` +Quando executamos o novo programa, ele nos dará uma lista de saída com todas as informações: +``` +$ ./genhd-for-import +{ + "mnemonic": "physical renew say quit enjoy eager topic remind riot concert refuse chair", + "account-xprv": "tprv8yxn8iFNgsLktEPkWKQpMqb7bcx5ViFQEbJMtqrGi8LEgvy8es6YeJvyJKrbYEPKMw8JbU3RFhNRQ4F2pataAtTNokS1JXBZVg62xfd5HCn", + "address": "tb1q9lhru6k0ymwrtr5w98w35n3lz22upml23h753n", + "derivation": "[d1280779/84h/1h/0h]" +} +``` +Temos o `mnemônico` que podemos recuperar, um `account-xprv` que podemos importar, uma `derivação` para usar para a importação e um `address` de amostra, que podemos usar para testar a importação. + +Agora podemos recorrer às lições aprendidas na seção [§3.5](03_5_Understanding_the_Descriptor.md) sobre como transformar esse xprv em um descritor e importá-lo. + +Primeiro, precisamos descobrir a soma de verificação: +``` +$ xprv=tprv8yxn8iFNgsLktEPkWKQpMqb7bcx5ViFQEbJMtqrGi8LEgvy8es6YeJvyJKrbYEPKMw8JbU3RFhNRQ4F2pataAtTNokS1JXBZVg62xfd5HCn +$ dp=[d1280779/84h/1h/0h] +$ bitcoin-cli getdescriptorinfo "wpkh($dp$xprv/0/*)" +{ + "descriptor": "wpkh([d1280779/84'/1'/0']tpubDWepH8HcqF2RmhRYPy5QmFFEAeU1f3SJotu9BMta8Q8dXRDuHFv8poYqUUtEiWftBjtKn1aNhi9Qg2P4NdzF66dShYvB92z78WJbYeHTLTz/0/*)#f8rmqc0z", + "checksum": "46c00dk5", + "isrange": true, + "issolvable": true, + "hasprivatekeys": true +} +``` + +Há três coisas a serem observadas aqui: + +1. Usamos o `wpkh` como a função em nosso caminho de derivação. Isso porque queremos gerar endereços Segwit modernos, não endereços legados. Isso corresponde ao uso na Libwally da função `wally_bip32_key_to_addr_segwit`. A coisa mais importante, entretanto, é ter as mesmas expectativas com a Libwally e o `bitcoin-cli` (e nosso descritor) de que tipo de endereço estamos gerando, para que tudo sê certo; +2. Usamos o caminho `/0/*` porque queríamos os endereços externos para esta conta. Se, em vez disso, quiséssemos alterar os endereços, usaríamos `/1/*`; +3. Não vamos usar a linha `descriptor` que foi retornada, pois é para um endereço `xpub`. Ao invés disso, aplicaremos o `checksum` retornado ao `xprv` que já temos. +``` +$ cs=$(bitcoin-cli getdescriptorinfo "wpkh($dp$xprv/0/*)" | jq -r ' .checksum') +``` +Então conectamos isso em um `importmulti` para importar esta chave no `bitcoin-cli`: +``` +$ bitcoin-cli importmulti '''[{ "desc": "wpkh('$dp''$xprv'/0/*)#'$cs'", "timestamp": "now", "range": 10, "watchonly": false, "label": "LibwallyImports", "keypool": false, "rescan": false }]''' +[ + { + "success": true + } +] + +``` +Aqui, importamos/geramos os primeiros dez endereços para a chave privada. + +Vamos examinar o novo rótulo `LibwallyImported`: +``` +$ bitcoin-cli getaddressesbylabel "LibwallyImports" +{ + "tb1qzeqrrt77xhvazq5g8sc9th0lzjwstknan8gzq7": { + "purpose": "receive" + }, + "tb1q9lhru6k0ymwrtr5w98w35n3lz22upml23h753n": { + "purpose": "receive" + }, + "tb1q8fsgxt0z9r9hfl5mst5ylxka2yljjxlxlvaf8j": { + "purpose": "receive" + }, + "tb1qg6dayhdk4qc6guutxvdweh6pctc9dpguu6awqc": { + "purpose": "receive" + }, + "tb1qdphaj0exvemxhgfpyh4p99wn84e2533u7p96l6": { + "purpose": "receive" + }, + "tb1qwv9mdqkpx6trtmvgw3l95npq8gk9pgllucvata": { + "purpose": "receive" + }, + "tb1qwh92pkrv6sps62udnmez65vfxe9n5ceuya56xz": { + "purpose": "receive" + }, + "tb1q4e98ln8xlym64qjzy3k8zyfyt5q60dgcn39d90": { + "purpose": "receive" + }, + "tb1qhzje887fyl65j4mulqv9ysmntwn95zpgmgvtqd": { + "purpose": "receive" + }, + "tb1q62xf9ec8zcfkh2qy5qnq4qcxrx8l0jm27dd8ru": { + "purpose": "receive" + }, + "tb1qlw85usfk446ssxejm9dmxsfn40kzsqce77aq20": { + "purpose": "receive" + } +} + +``` +O segundo em nossa lista realmente corresponde ao que temos de amostra (`tb1q9lhru6k0ymwrtr5w98w35n3lz22upml23h753n`). A importação desta chave privada e a derivação de dez endereços foram bem-sucedidas. + +Se olharmos agora para trás na seção [§7.3](07_3_Integrating_with_Hardware_Wallets.md), veremos que esta era a mesma metodologia que usamos para importar endereços de uma carteira física (embora desta vez também importamos a chave privada como prova de conceito). A maior diferença é que anteriormente a informação era criada por uma caixa preta (literalmente, pois era um dispositivo Ledger), e desta vez nós mesmos criamos a informação usando a Libwally, mostrando como podemos fazer esse tipo de trabalho de maneira airgaped ou em outro dispositivo remoto e, em seguida, levá-lo ao `bitcoin-cli`. + +## Importando endereços + +Obviamente, se podemos importar chaves privadas, também podemos importar endereços, o que geralmente significa importar endereços somente para observação _sem_ as chaves privadas. + +Uma maneira do fazer isso é utilizar a metodologia `importmulti` acima, mas neste caso, usamos o endereço fornecido XPUB (`wpkh([d1280779/84'/1'/0']tpubDWepH8HcqF2RmhRYPy5QmFFEAeU1f3SJotu9BMta8Q8dXRDuHFv8poYqUUtEiWftBjtKn1aNhi9Qg2P4NdzF66dShYvB92z78WJbYeHTLTz/0/*)#f8rmqc0z`) ao invés do xprv original. Essa é a melhor maneira de importar uma sequência inteira de endereços somente para observação. + +Como alternativa, podemos importar endereços individuais. Por exemplo, considere o único endereço de amostra retornado pelo programa `genhd-for-import`: +``` +$ ./genhd-for-import +{ + "mnemonic": "finish lady crucial walk illegal ride hamster strategy desert file twin nature", + "account-xprv": "tprv8xRujYeVN7CwBHxLoTHRdmzwdW7dKUzDfruSo56GqqfRW9QXtnxnaRG8ke7j65uNjxmCVfcagz5uuaMi2vVJ8jpiGZvLwahmNB8F3SHUSyv", + "address": "tb1qtvcchgyklp6cyleth85c7pfr4j72z2vyuwuj3d", + "derivation": "[6214ecff/84h/1h/0h]" +} +``` +Podemos importá-lo como um endereço de observação com `importaddress`: +``` +$ bitcoin-cli -named importaddress address=tb1qtvcchgyklp6cyleth85c7pfr4j72z2vyuwuj3d label=LibwallyWO rescan=false +$ bitcoin-cli getaddressesbylabel "LibwallyWO" +{ + "tb1qtvcchgyklp6cyleth85c7pfr4j72z2vyuwuj3d": { + "purpose": "receive" + } +} +} +``` + +## Resumo: Integrando o Libwally ao Bitcoin-CLI + +Com um conhecimento básico de Libwally, agora podemos complementar todo o trabalho das lições anteriores. A transferência de endereços, chaves, transações e PSBTs são apenas algumas das maneiras pelas quais podemos usar esses dois poderosos métodos de programação do Bitcoin juntos. Também há muito mais profundidade potencial se quisermos nos aprofundar na extensa biblioteca de funções do Libwally. + +> :fire: ***Qual é o poder de integrar Libwally e Bitcoin-CLI?*** Uma das maiores vantagens do Libwally é que ele tem muitas funções que podem ser usadas offline. Em comparação, o Bitcoin Core é um programa em rede. Isso pode ajudá-lo a aumentar a segurança fazendo com que o `bitcoin-cli` passe chaves, endereços, transações ou PSBTs para uma fonte offline (que estaria executando programas Libwally). Além disso, o Libwally pode fazer coisas que o Bitcoin Core não pode, como gerar uma seed a partir de um mnemônico BIP39 (e mesmo se não pudermos importá-la para o Bitcoin Core, _podemos_ importar a chave mestra, conforme mostrado aqui). + +## O Que Vem Depois? + +Saiba mais sobre outras linguagens de programação no [Capítulo 17: Conversando com o Bitcoind com Outras Linguagens](17_0_Talking_to_Bitcoind_Other.md). \ No newline at end of file From 317ca7e1955f9f03aba7d42d15be5e225f5d6a17 Mon Sep 17 00:00:00 2001 From: namcios Date: Mon, 23 Aug 2021 11:05:33 -0300 Subject: [PATCH 02/14] Delete old chapter 15 --- pt/15_0_Talking_to_Bitcoind.md | 27 -- pt/15_1_Accessing_Bitcoind_with_C.md | 294 --------------- pt/15_2_Programming_Bitcoind_with_C.md | 354 ------------------ ...Receiving_Bitcoind_Notifications_with_C.md | 155 -------- 4 files changed, 830 deletions(-) delete mode 100644 pt/15_0_Talking_to_Bitcoind.md delete mode 100644 pt/15_1_Accessing_Bitcoind_with_C.md delete mode 100644 pt/15_2_Programming_Bitcoind_with_C.md delete mode 100644 pt/15_3_Receiving_Bitcoind_Notifications_with_C.md diff --git a/pt/15_0_Talking_to_Bitcoind.md b/pt/15_0_Talking_to_Bitcoind.md deleted file mode 100644 index 88bde29..0000000 --- a/pt/15_0_Talking_to_Bitcoind.md +++ /dev/null @@ -1,27 +0,0 @@ - -# 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) - \ No newline at end of file diff --git a/pt/15_1_Accessing_Bitcoind_with_C.md b/pt/15_1_Accessing_Bitcoind_with_C.md deleted file mode 100644 index 2e97e1c..0000000 --- a/pt/15_1_Accessing_Bitcoind_with_C.md +++ /dev/null @@ -1,294 +0,0 @@ - -# 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 -#include -``` - -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). diff --git a/pt/15_2_Programming_Bitcoind_with_C.md b/pt/15_2_Programming_Bitcoind_with_C.md deleted file mode 100644 index c1fdc38..0000000 --- a/pt/15_2_Programming_Bitcoind_with_C.md +++ /dev/null @@ -1,354 +0,0 @@ - -# 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). \ No newline at end of file diff --git a/pt/15_3_Receiving_Bitcoind_Notifications_with_C.md b/pt/15_3_Receiving_Bitcoind_Notifications_with_C.md deleted file mode 100644 index fe166ac..0000000 --- a/pt/15_3_Receiving_Bitcoind_Notifications_with_C.md +++ /dev/null @@ -1,155 +0,0 @@ - -# 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=
- -zmqpubhashtx=
- -zmqpubrawblock=
- -zmqpubrawtx=
-``` - -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 -int main(int argc, char ** argv) { - - char *zmqserver; - char *topic; - - if(argc < 3) { - printf("\nUSAGE:\nchainlistener \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). \ No newline at end of file From 8512f44de417a412b85440e4a0b54a749658d30c Mon Sep 17 00:00:00 2001 From: namcios Date: Mon, 23 Aug 2021 11:11:25 -0300 Subject: [PATCH 03/14] Rename files chapter 16 to 17 --- ...ramming_with_Libwally.md => 17_0_Programming_with_Libwally.md} | 0 pt/{16_1_Setting_Up_Libwally.md => 17_1_Setting_Up_Libwally.md} | 0 ...Using_BIP39_in_Libwally.md => 17_2_Using_BIP39_in_Libwally.md} | 0 ...Using_BIP32_in_Libwally.md => 17_3_Using_BIP32_in_Libwally.md} | 0 ...Using_PSBTs_in_Libwally.md => 17_4_Using_PSBTs_in_Libwally.md} | 0 ...g_Scripts_in_Libwally.md => 17_5_Using_Scripts_in_Libwally.md} | 0 ...s_in_Libwally.md => 17_6_Using_Other_Functions_in_Libwally.md} | 0 ...itcoin-CLI.md => 17_7_Integrating_Libwally_and_Bitcoin-CLI.md} | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename pt/{16_0_Programming_with_Libwally.md => 17_0_Programming_with_Libwally.md} (100%) rename pt/{16_1_Setting_Up_Libwally.md => 17_1_Setting_Up_Libwally.md} (100%) rename pt/{16_2_Using_BIP39_in_Libwally.md => 17_2_Using_BIP39_in_Libwally.md} (100%) rename pt/{16_3_Using_BIP32_in_Libwally.md => 17_3_Using_BIP32_in_Libwally.md} (100%) rename pt/{16_4_Using_PSBTs_in_Libwally.md => 17_4_Using_PSBTs_in_Libwally.md} (100%) rename pt/{16_5_Using_Scripts_in_Libwally.md => 17_5_Using_Scripts_in_Libwally.md} (100%) rename pt/{16_6_Using_Other_Functions_in_Libwally.md => 17_6_Using_Other_Functions_in_Libwally.md} (100%) rename pt/{16_7_Integrating_Libwally_and_Bitcoin-CLI.md => 17_7_Integrating_Libwally_and_Bitcoin-CLI.md} (100%) diff --git a/pt/16_0_Programming_with_Libwally.md b/pt/17_0_Programming_with_Libwally.md similarity index 100% rename from pt/16_0_Programming_with_Libwally.md rename to pt/17_0_Programming_with_Libwally.md diff --git a/pt/16_1_Setting_Up_Libwally.md b/pt/17_1_Setting_Up_Libwally.md similarity index 100% rename from pt/16_1_Setting_Up_Libwally.md rename to pt/17_1_Setting_Up_Libwally.md diff --git a/pt/16_2_Using_BIP39_in_Libwally.md b/pt/17_2_Using_BIP39_in_Libwally.md similarity index 100% rename from pt/16_2_Using_BIP39_in_Libwally.md rename to pt/17_2_Using_BIP39_in_Libwally.md diff --git a/pt/16_3_Using_BIP32_in_Libwally.md b/pt/17_3_Using_BIP32_in_Libwally.md similarity index 100% rename from pt/16_3_Using_BIP32_in_Libwally.md rename to pt/17_3_Using_BIP32_in_Libwally.md diff --git a/pt/16_4_Using_PSBTs_in_Libwally.md b/pt/17_4_Using_PSBTs_in_Libwally.md similarity index 100% rename from pt/16_4_Using_PSBTs_in_Libwally.md rename to pt/17_4_Using_PSBTs_in_Libwally.md diff --git a/pt/16_5_Using_Scripts_in_Libwally.md b/pt/17_5_Using_Scripts_in_Libwally.md similarity index 100% rename from pt/16_5_Using_Scripts_in_Libwally.md rename to pt/17_5_Using_Scripts_in_Libwally.md diff --git a/pt/16_6_Using_Other_Functions_in_Libwally.md b/pt/17_6_Using_Other_Functions_in_Libwally.md similarity index 100% rename from pt/16_6_Using_Other_Functions_in_Libwally.md rename to pt/17_6_Using_Other_Functions_in_Libwally.md diff --git a/pt/16_7_Integrating_Libwally_and_Bitcoin-CLI.md b/pt/17_7_Integrating_Libwally_and_Bitcoin-CLI.md similarity index 100% rename from pt/16_7_Integrating_Libwally_and_Bitcoin-CLI.md rename to pt/17_7_Integrating_Libwally_and_Bitcoin-CLI.md From 2502bd075165bc836a740d57d266120f7815ae12 Mon Sep 17 00:00:00 2001 From: namcios Date: Mon, 23 Aug 2021 11:24:22 -0300 Subject: [PATCH 04/14] Update README --- pt/README.md | 56 ++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/pt/README.md b/pt/README.md index 2917302..0f155f5 100644 --- a/pt/README.md +++ b/pt/README.md @@ -105,40 +105,40 @@ Se você gostaria de fazer a sua própria tradução, por favor veja [Contribuin **Estado:** Finalizado. -* [15.0: Conversando com o Bitcoind com C](15_0_Talking_to_Bitcoind.md) - * [15.1: Acessando o Bitcoind em C com Livrarias RPC](15_1_Accessing_Bitcoind_with_C.md) - * [15.2: Programando o Bitcoind em C com Livrarias RPC](15_2_Programming_Bitcoind_with_C.md) - * [15.3: Recebendo Notificações em C com Livrarias ZMQ](15_3_Receiving_Bitcoind_Notifications_with_C.md) -* [16.0: Programando Bitcoin com Libwally](16_0_Programming_with_Libwally.md) - * [16.1: Configurando a Libwally](16_1_Setting_Up_Libwally.md) - * [16.2: Usando BIP39 na Libwally](16_2_Using_BIP39_in_Libwally.md) - * [16.3: Usando BIP32 na Libwally](16_3_Using_BIP32_in_Libwally.md) - * [16.4: Usando PSBTs na Libwally](16_4_Using_PSBTs_in_Libwally.md) - * [16.5: Usando Scripts na Libwally](16_5_Using_Scripts_in_Libwally.md) - * [16.6: Usando Outras Funções na Libwally](16_6_Using_Other_Functions_in_Libwally.md) - * [16.7: Integrando Libwally e Bitcoin-CLI](16_7_Integrating_Libwally_and_Bitcoin-CLI.md) -* [17.0: Conversando com o Bitcoind com Outras Linguagens](17_0_Talking_to_Bitcoind_Other.md) - * [17.1: Acessando o Bitcoind com Go](17_1_Accessing_Bitcoind_with_Go.md) - * [17.2: Acessando o Bitcoind com Java](17_2_Accessing_Bitcoind_with_Java.md) - * [17.3: Acessando o Bitcoind com Node JS](17_3_Accessing_Bitcoind_with_NodeJS.md) - * [17.4: Acessando o Bitcoind com Python](17_4_Accessing_Bitcoind_with_Python.md) - * [17.5: Acessando o Bitcoind com Rust](17_5_Accessing_Bitcoind_with_Rust.md) - * [17.6: Acessando o Bitcoind com Swift](17_6_Accessing_Bitcoind_with_Swift.md) +* [16.0: Conversando com o Bitcoind com C](15_0_Talking_to_Bitcoind.md) + * [16.1: Acessando o Bitcoind em C com Livrarias RPC](15_1_Accessing_Bitcoind_with_C.md) + * [16.2: Programando o Bitcoind em C com Livrarias RPC](15_2_Programming_Bitcoind_with_C.md) + * [16.3: Recebendo Notificações em C com Livrarias ZMQ](15_3_Receiving_Bitcoind_Notifications_with_C.md) +* [17.0: Programando Bitcoin com Libwally](16_0_Programming_with_Libwally.md) + * [17.1: Configurando a Libwally](16_1_Setting_Up_Libwally.md) + * [17.2: Usando BIP39 na Libwally](16_2_Using_BIP39_in_Libwally.md) + * [17.3: Usando BIP32 na Libwally](16_3_Using_BIP32_in_Libwally.md) + * [17.4: Usando PSBTs na Libwally](16_4_Using_PSBTs_in_Libwally.md) + * [17.5: Usando Scripts na Libwally](16_5_Using_Scripts_in_Libwally.md) + * [17.6: Usando Outras Funções na Libwally](16_6_Using_Other_Functions_in_Libwally.md) + * [17.7: Integrando Libwally e Bitcoin-CLI](16_7_Integrating_Libwally_and_Bitcoin-CLI.md) +* [18.0: Conversando com o Bitcoind com Outras Linguagens](17_0_Talking_to_Bitcoind_Other.md) + * [18.1: Acessando o Bitcoind com Go](17_1_Accessing_Bitcoind_with_Go.md) + * [18.2: Acessando o Bitcoind com Java](17_2_Accessing_Bitcoind_with_Java.md) + * [18.3: Acessando o Bitcoind com Node JS](17_3_Accessing_Bitcoind_with_NodeJS.md) + * [18.4: Acessando o Bitcoind com Python](17_4_Accessing_Bitcoind_with_Python.md) + * [18.5: Acessando o Bitcoind com Rust](17_5_Accessing_Bitcoind_with_Rust.md) + * [18.6: Acessando o Bitcoind com Swift](17_6_Accessing_Bitcoind_with_Swift.md) ### PARTE SEIS: USANDO LIGHTNING-CLI **Estado:** Finalizado. -* [18.0: Compreendendo Sua Configuração Lightning](18_0_Understanding_Your_Lightning_Setup.md) - * [18.1: Verificando Sua Configuração c-lightning](18_1_Verifying_Your_Lightning_Setup.md) - * [18.2: Conhecendo Sua Configuração c-lightning](18_2_Knowing_Your_lightning_Setup.md) +* [19.0: Compreendendo Sua Configuração Lightning](18_0_Understanding_Your_Lightning_Setup.md) + * [19.1: Verificando Sua Configuração c-lightning](18_1_Verifying_Your_Lightning_Setup.md) + * [19.2: Conhecendo Sua Configuração c-lightning](18_2_Knowing_Your_lightning_Setup.md) * [Prefácio: Acessando um Segundo Node Lightning](18_2__Interlude_Accessing_a_Second_Lightning_Node.md) - * [18.3: Criando um Canal Lightning](18_3_Setting_Up_a_Channel.md) -* [19.0: Usando Lightning](19_0_Using_Lightning.md) - * [19.1: Gerando um Pedido de Pagamento](19_1_Generate_a_Payment_Request.md) - * [19.2: Pagando uma Fatura](19_2_Paying_a_Invoice.md) - * [19.3: Fechando um Canal Lighnting]((19_3_Closing_a_Channel.md)) - * [19.4: Expandindo a Rede Lightning](19_4_Lightning_Network_Review.md) + * [19.3: Criando um Canal Lightning](18_3_Setting_Up_a_Channel.md) +* [20.0: Usando Lightning](19_0_Using_Lightning.md) + * [20.1: Gerando um Pedido de Pagamento](19_1_Generate_a_Payment_Request.md) + * [20.2: Pagando uma Fatura](19_2_Paying_a_Invoice.md) + * [20.3: Fechando um Canal Lighnting]((19_3_Closing_a_Channel.md)) + * [20.4: Expandindo a Rede Lightning](19_4_Lightning_Network_Review.md) ### APÊNDICES From c3578c8c1f2becd9e37aa3ad8d5ef18ddfb513df Mon Sep 17 00:00:00 2001 From: namcios Date: Mon, 23 Aug 2021 11:26:45 -0300 Subject: [PATCH 05/14] Update README --- pt/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pt/README.md b/pt/README.md index 0f155f5..0086802 100644 --- a/pt/README.md +++ b/pt/README.md @@ -101,6 +101,9 @@ Se você gostaria de fazer a sua própria tradução, por favor veja [Contribuin * [14.2: Mudando Seus Serviços Ocultos do Bitcoin](14_2_Changing_Your_Bitcoin_Hidden_Services.md) * [14.3: Adicionando SSH aos Seus Serviços Ocultos](14_3_Adding_SSH_Hidden_Services.md) +* [15.0: Usando i2p](15_0_Using_i2p.md) + * [15.1: Bitcoin Core como um Serviço I2P (Invisible Internet Project)](15_1_i2p_service.md) + ### PARTE CINCO: PROGRAMANDO COM RPC **Estado:** Finalizado. From cfee6bc11907ed55a22cde29af04b65972eb79fb Mon Sep 17 00:00:00 2001 From: namcios Date: Mon, 23 Aug 2021 11:39:22 -0300 Subject: [PATCH 06/14] Review 17_0 --- pt/17_0_Programming_with_Libwally.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pt/17_0_Programming_with_Libwally.md b/pt/17_0_Programming_with_Libwally.md index 735b8ae..dab6205 100644 --- a/pt/17_0_Programming_with_Libwally.md +++ b/pt/17_0_Programming_with_Libwally.md @@ -1,14 +1,14 @@ -# Capítulo 16: Programando com Libwally +# Capítulo 17: Programando com Libwally -O capítulo anterior apresentou três bibliotecas C, para RPC, JSON e ZMQ, todas destinadas a interagir diretamente com o `bitcoind`, assim como você vem fazendo desde o início. Mas, às vezes você pode querer codificar sem acesso direto a um `bitcoind`. Isso pode ser devido a um cliente offline ou apenas porque você deseja manter algumas funcionalidades internas de seu programa C. Você também pode querer se aprofundar na funcionalidade da carteira, como criação de palavras mnemônicas ou derivação de endereços. É aí que entra Libwally: é uma biblioteca de carteira para C, C ++, Java, NodeJS ou Python, com wrappers também disponíveis para outras linguagens, como Swift. +O capítulo anterior apresentou três bibliotecas C, para RPC, JSON e ZMQ, todas destinadas a interagir diretamente com o `bitcoind`, assim como você vem fazendo desde o início. Mas às vezes você pode querer codificar sem acesso direto a um `bitcoind`. Isso pode ser devido a um cliente offline ou apenas porque você deseja manter algumas funcionalidades internas de seu programa C. Você também pode querer se aprofundar na funcionalidade da carteira, como criação de palavras mnemônicas ou derivação de endereços. É aí que entra Libwally: é uma biblioteca de carteira para C, C ++, Java, NodeJS ou Python, com wrappers também disponíveis para outras linguagens, como Swift. -Este capítulo aborda a funcionalidade possível dentro do Libwally, a maioria das quais complementa o trabalho que você fez através do acesso RPC ao `bitcoind`, mas algumas das quais o replicam. Ele também mostra como integrar esse trabalho com os clientes RPC com os quais você está mais familiarizado. No entanto, observe que esta é apenas uma introdução básica ao Libwally. Vários de seus conjuntos de funções mais importantes são destacados, mas nunca fazemos mais do que enfiar os pés no chão. Se você acha suas funções úteis ou intrigantes, então você precisará se aprofundar muito mais profundamente do que este curso pode cobrir. +Este capítulo aborda a funcionalidade possível dentro do Libwally, a maioria das quais complementa o trabalho que você fez através do acesso RPC ao `bitcoind`, mas algumas das quais o replicam. Ele também mostra como integrar esse trabalho com os clientes RPC com os quais você está mais familiarizado. No entanto, observe que esta é apenas uma introdução básica ao Libwally. Vários de seus conjuntos de funções mais importantes são destacados, mas nunca fazemos mais do que apresentar uma introdução. Se você acha suas funções úteis ou intrigantes, então você precisará se aprofundar muito mais do que este curso pode cobrir. -## Objetivos deste capítulo +## Objetivos Deste Capítulo Depois de trabalhar neste capítulo, um desenvolvedor será capaz de: - * Usar as funções da carteira com o Libwally; + * Usar as funções de carteira com o Libwally; * Realizar manipulações de PSBTs e transações com o Libwally; * Implementar designs que combinem o Libwally e o RPC. @@ -20,10 +20,10 @@ Os objetivos secundários do capítulo incluem a capacidade de: ## Tabela de Conteúdo - * [Seção 1: Configurando o Libwally](16_1_Setting_Up_Libwally.md) - * [Seção 2: Usando o BIP39 no Libwally](16_2_Using_BIP39_in_Libwally.md) - * [Seção 3: Usando o BIP32 no Libwally](16_3_Using_BIP32_in_Libwally.md) - * [Seção 4: Usando o PSBTs no Libwally](16_4_Using_PSBTs_in_Libwally.md) - * [Seção 5: Usando Scripts no Libwally](16_5_Using_Scripts_in_Libwally.md) - * [Seção 6: Usando Outras Funções no Libwally](16_6_Using_Other_Functions_in_Libwally.md) - * [Seção 7: Integrando o Libwally ao Bitcoin-CLI](16_7_Integrating_Libwally_and_Bitcoin-CLI.md) \ No newline at end of file + * [Seção 1: Configurando o Libwally](17_1_Setting_Up_Libwally.md) + * [Seção 2: Usando o BIP39 no Libwally](17_2_Using_BIP39_in_Libwally.md) + * [Seção 3: Usando o BIP32 no Libwally](17_3_Using_BIP32_in_Libwally.md) + * [Seção 4: Usando os PSBTs no Libwally](17_4_Using_PSBTs_in_Libwally.md) + * [Seção 5: Usando Scripts no Libwally](17_5_Using_Scripts_in_Libwally.md) + * [Seção 6: Usando Outras Funções no Libwally](17_6_Using_Other_Functions_in_Libwally.md) + * [Seção 7: Integrando o Libwally ao Bitcoin-CLI](17_7_Integrating_Libwally_and_Bitcoin-CLI.md) \ No newline at end of file From dcb45e5ec76d3a03a1e3b29642490bec776ff026 Mon Sep 17 00:00:00 2001 From: namcios Date: Mon, 23 Aug 2021 11:41:06 -0300 Subject: [PATCH 07/14] Minor fixes on 17_0 --- pt/17_0_Programming_with_Libwally.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pt/17_0_Programming_with_Libwally.md b/pt/17_0_Programming_with_Libwally.md index dab6205..238269b 100644 --- a/pt/17_0_Programming_with_Libwally.md +++ b/pt/17_0_Programming_with_Libwally.md @@ -20,10 +20,10 @@ Os objetivos secundários do capítulo incluem a capacidade de: ## Tabela de Conteúdo - * [Seção 1: Configurando o Libwally](17_1_Setting_Up_Libwally.md) - * [Seção 2: Usando o BIP39 no Libwally](17_2_Using_BIP39_in_Libwally.md) - * [Seção 3: Usando o BIP32 no Libwally](17_3_Using_BIP32_in_Libwally.md) - * [Seção 4: Usando os PSBTs no Libwally](17_4_Using_PSBTs_in_Libwally.md) - * [Seção 5: Usando Scripts no Libwally](17_5_Using_Scripts_in_Libwally.md) - * [Seção 6: Usando Outras Funções no Libwally](17_6_Using_Other_Functions_in_Libwally.md) - * [Seção 7: Integrando o Libwally ao Bitcoin-CLI](17_7_Integrating_Libwally_and_Bitcoin-CLI.md) \ No newline at end of file + * [Seção 1: Configurando a Libwally](17_1_Setting_Up_Libwally.md) + * [Seção 2: Usando BIP39 na Libwally](17_2_Using_BIP39_in_Libwally.md) + * [Seção 3: Usando BIP32 na Libwally](17_3_Using_BIP32_in_Libwally.md) + * [Seção 4: Usando PSBTs na Libwally](17_4_Using_PSBTs_in_Libwally.md) + * [Seção 5: Usando Scripts na Libwally](17_5_Using_Scripts_in_Libwally.md) + * [Seção 6: Usando Outras Funções na Libwally](17_6_Using_Other_Functions_in_Libwally.md) + * [Seção 7: Integrando Libwally e Bitcoin-CLI](17_7_Integrating_Libwally_and_Bitcoin-CLI.md) \ No newline at end of file From acc04c5ec3650ab75024036de23e20e5b365c6c6 Mon Sep 17 00:00:00 2001 From: namcios Date: Mon, 23 Aug 2021 11:48:03 -0300 Subject: [PATCH 08/14] Review 17_1 --- pt/17_1_Setting_Up_Libwally.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/pt/17_1_Setting_Up_Libwally.md b/pt/17_1_Setting_Up_Libwally.md index 990b800..2e24409 100644 --- a/pt/17_1_Setting_Up_Libwally.md +++ b/pt/17_1_Setting_Up_Libwally.md @@ -4,9 +4,9 @@ Esta primeira seção explicará como fazer o download da Biblioteca Libwally C e como colocá-la em funcionamento. -> :book: ***O que é a Libwally?*** A Libwally é uma biblioteca de primitivas útil para a criação de carteiras que é totalmente multiplataforma, de modo que as mesmas funções possam ser usadas em qualquer lugar. Existem [documentação online](https://wally.readthedocs.io/en/latest/), caso esteja interessado. A Libwally está disponível como parte do [Elements Project](https://github.com/ElementsProject) da Blockstream. +> :book: ***O que é a Libwally?*** A Libwally é uma biblioteca de primitivas útil para a criação de carteiras que é totalmente multiplataforma, de modo que as mesmas funções possam ser usadas em qualquer lugar. Há uma [documentação online](https://wally.readthedocs.io/en/latest/), caso esteja interessado. A Libwally está disponível como parte do [Elements Project](https://github.com/ElementsProject) da Blockstream. -## Instalando o Libwally +## Instalando a Libwally Como de costume, precisaremos de alguns pacotes no nosso sistema: ``` @@ -17,7 +17,6 @@ Podemos então fazer o download do Libwally com base no seu repositório Git: ``` $ git clone https://github.com/ElementsProject/libwally-core ``` -Afterward, you can begin the configuration process: Depois, podemos começar com o processo de configuração. ``` $ ./tools/autogen.sh @@ -90,11 +89,11 @@ Finalmente, podemos instalar: $ sudo make install ``` -## Nos preparando para a Libwally +## Nos Preparando Para a Libwally -Então, como usamos a Libwally em nosso programa que estamos construindo? Como de costume, precisaremos incluir os arquivos e vincular as bibliotecas apropriadas em nosso código. +Então, como usamos a Libwally em um programa? Como de costume, precisaremos incluir os arquivos e vincular as bibliotecas apropriadas em nosso código. -### Incluindo os arquivos +### Incluindo os Arquivos Há um número considerável de arquivos que podemos incluir: @@ -106,7 +105,7 @@ $ ls /usr/include/wally* ``` Felizmente, os nomes dos arquivos correspondem amplamente às seções da [documentação](https://wally.readthedocs.io/en/latest/), então devemos ser capazes de incluir os arquivos corretos com base no que estamos fazendo, depois de incluir o onipresente `wally_core.h`. -### Vinculando as bibliotecas +### Vinculando as Bibliotecas Também precisaremos vincular as bibliotecas apropriadas: ``` @@ -116,7 +115,7 @@ $ ls /usr/lib/libsecp* /usr/lib/libwally* ``` Usaremos principalmente a `libwallycore`. -## Configurando um programa Libwally +## Configurando um Programa Libwally Comparado com algumas das bibliotecas anteriores, a Libwally é ridiculamente fácil de ser inicializada: ``` @@ -128,7 +127,7 @@ wally_cleanup(0); ``` Em ambos os casos, o argumento é para flags, mas atualmente está definido como `0`. -## Testando um programa de teste da Libwally +## Testando um Programa de Teste da Libwally O diretório src contém o arquivo [testwally.c](src / 16_1_testwally.c), que apenas mostra como funcionam as funções de inicialização e de limpeza. @@ -150,7 +149,7 @@ include/wally_core.h:#define WALLY_OK 0 /** Success */ Também precisamos instalar o Libsodium para obter acesso a um gerador de números aleatórios de alta qualidade para fins de teste. -> :warning: **AVISO:** A geração de números aleatórios pode ser um dos maiores pontos de vulnerabilidade em qualquer software do Bitcoin. Se fizermos isso de maneira errada, podemos export nossos usuários a ataques porque eles acabam tendo chaves privadas do Bitcoin inseguras, e isso não é um [problema teórico](https://github.com/BlockchainCommons/SmartCustodyBook/blob/master/manuscript/ 03-adversaries.md # adversary-systemic-key-compromise). A BlockchainInfo gerou incorretamente 0,0002% das suas chaves, o que resultou na perda temporária de 250 Bitcoins. Resumindo: Precisamos nos certificar de estar totalmente confortável com a geração de números aleatórios. Podemos usar o Libsodium ou qualquer outro método TRNG ainda mais robusto. +> :warning: **AVISO:** A geração de números aleatórios pode ser um dos maiores pontos de vulnerabilidade em qualquer software do Bitcoin. Se fizermos isso de maneira errada, podemos expor nossos usuários a ataques porque eles acabam tendo chaves privadas do Bitcoin inseguras, e isso não é um [problema teórico](https://github.com/BlockchainCommons/SmartCustodyBook/blob/master/manuscript/03-adversaries.md#adversary-systemic-key-compromise). A BlockchainInfo gerou incorretamente 0,0002% das suas chaves, o que resultou na perda temporária de 250 Bitcoins. Resumindo: precisamos nos certificar de estar totalmente confortável com a geração de números aleatórios. Podemos usar o Libsodium ou qualquer outro método TRNG ainda mais robusto. Podemos baixar um [Libsodium tarball](https://download.libsodium.org/libsodium/releases/) e seguir as instruções em [instalação do Libsodium](https://doc.libsodium.org/installation) para deixarmos tudo pronto em nosso computador. @@ -193,4 +192,4 @@ Então, o que exatamente podemos fazer agora? É para dar essa resposta que temo ## O Que Vem Depois? -Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.2: Usando o BIP39 no Libwally](16_2_Using_BIP39_in_Libwally.md). \ No newline at end of file +Vamos aprender mais sobre "Programando Bitcoin com Libwally" na seção [§16.2: Usando BIP39 na Libwally](16_2_Using_BIP39_in_Libwally.md). \ No newline at end of file From 8dbcbd76e245730a81b16f95425fc16ec1a89b71 Mon Sep 17 00:00:00 2001 From: namcios Date: Mon, 23 Aug 2021 12:09:13 -0300 Subject: [PATCH 09/14] Review 17_2 --- pt/17_2_Using_BIP39_in_Libwally.md | 44 +++++++++++++++--------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/pt/17_2_Using_BIP39_in_Libwally.md b/pt/17_2_Using_BIP39_in_Libwally.md index 4669828..e8ab746 100644 --- a/pt/17_2_Using_BIP39_in_Libwally.md +++ b/pt/17_2_Using_BIP39_in_Libwally.md @@ -1,20 +1,20 @@ -# 16.2: Usando o BIP39 no Libwally +# 16.2: Usando BIP39 na Libwally > :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. -Um dos maiores poderes de Libwally é que ele pode revelar o trabalho oculto da geração de seeds, chaves privadas e, também, de endereços. Para começar, ele suporta o [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki), que é o BIP que define códigos mnemônicos para o Bitcoin, algo que é totalmente incompatível, na época, com o Bitcoin Core. +Um dos maiores poderes da Libwally é que ela pode revelar o trabalho oculto da geração de seeds, chaves privadas e, também, de endereços. Para começar, ela suporta o [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki), que é o BIP que define códigos mnemônicos para o Bitcoin, algo que era totalmente incompatível, na época, com o Bitcoin Core. -> :book: ***O que é um código mnemônico?*** Os endereços de Bitcoin (e suas chaves privadas correspondentes e as suas seeds) são listas longas e ininteligíveis de caracteres e números, que não são apenas impossíveis de serem lembrados, mas também fáceis de serem digitados erroneamente. Os códigos mnemônicos são uma solução para isso que permitem aos usuários gravar 12 (ou 24) palavras em inglês, algo que é muito menos sujeito a erros. Esses códigos podem ser usados para restaurar totalmente uma seed BIP32 que é a base de uma carteira Determinística Hierárquica. +> :book: ***O que é um código mnemônico?*** Os endereços de Bitcoin (e suas chaves privadas correspondentes e as suas seeds) são listas longas e ininteligíveis de caracteres e números que não apenas são impossíveis de serem lembrados, mas também fáceis de serem digitados erroneamente. Os códigos mnemônicos são uma solução para isso que permitem aos usuários gravar 12 (ou 24) palavras em inglês, algo que é muito menos sujeito a erros. Esses códigos podem ser usados para restaurar totalmente uma seed BIP32 que é a base de uma carteira Determinística Hierárquica (HD). -> :book: ***O que é uma seed?*** Nós falamos brevemente das seeds na seção [§3.5: Compreendendo o descritor](03_5_Understanding_the_Descriptor.md). É o número aleatório usado para gerar uma sequência inteira de chaves privadas (e, portanto, endereços) em uma carteira Determinística Hierárquica. Voltaremos às seeds na próxima seção, onde falaremos sobre as carteiras Determinísticas Hierárquicas e a Libwally. Por enquanto, apenas é necessário saber que um código mnemônico BIP39 corresponde à seed para uma carteira determinística hierárquica do BIP32. +> :book: ***O que é uma seed?*** Nós falamos brevemente das seeds na seção [§3.5: Compreendendo o Descritor](03_5_Understanding_the_Descriptor.md). É o número aleatório usado para gerar uma sequência inteira de chaves privadas (e, portanto, endereços) em uma carteira HD. Voltaremos às seeds na próxima seção, onde falaremos sobre as carteiras HD e a Libwally. Por enquanto, apenas é necessário saber que um código mnemônico BIP39 corresponde à seed para uma carteira HD do BIP32. ## Criando Códigos Mnemônicos -Todas as chaves Bitcoin começam com a entropia. Este primeiro uso de Libwally, e os mnemônicos BIP39, mostram como gerar entropia e obter um código mnemônico a partir disso. +Todas as chaves Bitcoin começam com a entropia. Este primeiro uso da Libwally, e os mnemônicos BIP39, mostram como gerar entropia e obter um código mnemônico a partir disso. -> :book: ***O que é entropia?*** Entropia é uma maneira sofisticada de dizer aleatoriedade, mas é uma aleatoriedade medida cuidadosamente que é usada como a base de um número aleatório gerado verdadeiramente (no inglês, true-random-number generated, TRG). É medido em "bits", com mais bits de entropia resultando em mais aleatoriedade (e, portanto, mais proteção para o que está sendo gerado). Para o Bitcoin, a entropia é a base de nossa seed, que em uma carteira Determinística Hierárquica que gera todos os seus endereços. +> :book: ***O que é entropia?*** Entropia é uma maneira sofisticada de dizer aleatoriedade, mas é uma aleatoriedade medida cuidadosamente que é usada como a base de um número aleatório gerado verdadeiramente (no inglês, true-random-number generated, TRG). É medido em "bits", com mais bits de entropia resultando em mais aleatoriedade (e, portanto, mais proteção para o que está sendo gerado). Para o Bitcoin, a entropia é a base de nossa seed, que em uma carteira HD gera todos os seus endereços. -Sempre começaremos a trabalhar com a Libwally inicializando a biblioteca e testando os resultados, conforme demonstrado pela primeira vez na seção [§16.1](16_1_Setting_Up_Libwally.md): +Sempre começaremos a trabalhar com a Libwally inicializando a biblioteca e testando os resultados, conforme demonstrado pela primeira vez na seção [§17.1](17_1_Setting_Up_Libwally.md): ``` int lw_response; @@ -29,9 +29,9 @@ Sempre começaremos a trabalhar com a Libwally inicializando a biblioteca e test ``` Agora estamos prontos para a entropia. -### Criando a Entropia +### Criando Entropia -Usando o `libsodium`, podemos criar a entropia com o comando `randombytes_buf`: +Usando o `libsodium`, podemos criar entropia com o comando `randombytes_buf`: ``` unsigned char entropy[16]; randombytes_buf(entropy, 16); @@ -40,26 +40,26 @@ Este exemplo, que será a única maneira de usarmos a biblioteca `libsodium`, cr > :warning: **AVISO:** Mais uma vez, certifique-se de estar muito confortável com o método de geração de entropia antes de usá-lo em um programa do mundo real. -### Traduzindo para um mnemônico +### Traduzindo para um Mnemônico 16 bytes de entropia são suficientes para criar um código Mnemônico de 12 caracteres, que é feito com a função `bip39_mnemonic_from_bytes` da Libwally: ``` char *mnem = NULL; lw_response = bip39_mnemonic_from_bytes(NULL,entropy,16,&mnem); ``` -Observe que temos que passar o tamanho do byte, então se quiser aumentar o tamanho da entropia, para gerar uma frase mnemônica mais longa, também precisaria aumentar o valor nesta função. +Observe que temos que passar o tamanho do byte, então se quisermos aumentar o tamanho da entropia, para gerar uma frase mnemônica mais longa, também precisaríamos aumentar o valor nesta função. > **NOTA:** Existem listas de palavras mnemônicas para diferentes idiomas! O padrão é usar a lista do idioma inglês, que é a variável `NULL` nesses comandos mnemônicos da Libwally, mas podemos, alternativamente, solicitar um idioma diferente! É isso! Nós criamos uma frase mnemônica! -> :book: ***Como a frase mnemônica é criada?*** Podemos aprender mais sobre isso no [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki), mas se preferir, Greg Walker tem um [excelente exemplo](https://learnmeabitcoin.com/technical/mnemonic): De maneira geral, adicionamos uma soma de verificação e convertemos cada conjunto de 11 bits em uma palavra da lista de palavras. Podemos fazer isso com os comandos `bip39_get_wordlist` e `bip39_get_word` se não confiarmos no comando `bip39_mnemonic_from_bytes`. +> :book: ***Como a frase mnemônica é criada?*** Podemos aprender mais sobre isso no [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki), mas, se preferir, Greg Walker tem um [excelente exemplo](https://learnmeabitcoin.com/technical/mnemonic): de maneira geral, adicionamos um checksum e convertemos cada conjunto de 11 bits em uma palavra da lista de palavras. Podemos fazer isso com os comandos `bip39_get_wordlist` e `bip39_get_word` se não confiarmos no comando `bip39_mnemonic_from_bytes`. -### Traduzindo para uma seed +### Traduzindo para uma Seed -Existem algumas funções, como o `bip32_key_from_seed` (que veremos na próxima seção) que requerem que tenhamos os bits ao invés do Mnemônico. As duas coisas são funcionalmente idênticas, se temos a seed, pode gerar o mnemônico e vice-versa. +Existem algumas funções, como o `bip32_key_from_seed` (que veremos na próxima seção) que requerem que tenhamos os bits ao invés do Mnemônico. As duas coisas são funcionalmente idênticas: se temos a seed, podemos gerar o mnemônico e vice-versa. -Se você precisarmos gerar a seed a partir do nosso mnemônico, basta usar o comando `bip39_mnemonic_to_seed`: +Se precisarmos gerar a seed a partir do nosso mnemônico, basta usar o comando `bip39_mnemonic_to_seed`: ``` unsigned char seed[BIP39_SEED_LEN_512]; size_t seed_len; @@ -68,9 +68,9 @@ Se você precisarmos gerar a seed a partir do nosso mnemônico, basta usar o com ``` Observe que todas as seeds do BIP39 têm 512 bytes; no entanto, devemos definir o tamanho de nossa variável apropriadamente e passar o tamanho para o `bip39_mnemonic_to_seed`. -### Mostrando na Tela a Nossa Seed +### Vendo a Nossa Seed -Se quisermos ver como nossa semente se parece em hexadecimal, podemos usar a função `wally_hex_from_bytes` para transformar nossa seed em um código hexadecimal legível (mas isso não é muito bom para pessoas): +Se quisermos ver como nossa seed é em hexadecimal, podemos usar a função `wally_hex_from_bytes` para transformar nossa seed em um código hexadecimal legível (mas isso não é muito bom para pessoas): ``` char *seed_hex; wally_hex_from_bytes(seed,sizeof(seed),&seed_hex); @@ -82,7 +82,7 @@ Se dizermos tudo certo, devemos obter uma seed de 64 bytes. (Essa é a variável ## Testando o Código Mnemônico -O código completo para gerar entropia, gerar um mnemônico BIP39, validar o mnemônico e gerar uma seed pode ser encontrado no [diretório src/](src/16_2_genmnemonic.c). Podemos fazer o download e compilar: +O código completo para gerar entropia, gerar um mnemônico BIP39, validar o mnemônico e gerar uma seed pode ser encontrado no [diretório src/](src/17_2_genmnemonic.c). Podemos fazer o download e compilar: ``` $ cc genmnemonic.c -lwallycore -lsodium -o genmnemonic ``` @@ -93,14 +93,14 @@ Mnemonic validated! Seed: 47b04cfb5d8fd43d371497f8555a27a25ca0a04aafeb6859dd4cbf37f6664b0600c4685c1efac29c082b1df29081f7a46f94a26f618fc6fd38d8bc7b6cd344c7 ``` -## Resumo: Usando o BIP39 no Libwally +## Resumo: Usando BIP39 na Libwally -O BIP39 permite que possamos gerar um conjunto de 12-24 palavras Mnemônicas a partir de uma seed e a biblioteca Libwally também permite que a validemos! +O BIP39 nos permite gerar um conjunto de 12-24 palavras Mnemônicas a partir de uma seed (e a biblioteca Libwally também permite que a validemos!). > :fire: ***Qual é o poder do BIP39?*** Seeds de Bitcoin e chaves privadas estão sujeitas a todos os tipos de perda. Se digitarmos errado um único dígito, nosso dinheiro será perdido para sempre. Palavras mnemônicas são uma forma muito mais amigável de representar os mesmos dados, mas como são palavras no idioma de escolha do usuário, são menos sujeitas a erros. O poder do BIP39 é, portanto, melhorar a acessibilidade, usabilidade e segurança do Bitcoin. -> :fire: ***Qual é o poder do BIP39 na Libwally?*** O Bitcoind atualmente não suporta palavras mnemônicas, então usar a Libwally pode permitir que geremos palavras mnemônicas em conjunto com endereços mantidos no `bitcoind`, embora como veremos na seção §16.7, é necessário um pouco de gambiarra para importar suas chaves para o Bitcoin Core. +> :fire: ***Qual é o poder do BIP39 na Libwally?*** O Bitcoind atualmente não suporta palavras mnemônicas, então usar a Libwally pode permitir que geremos palavras mnemônicas em conjunto com endereços mantidos no `bitcoind`, embora como veremos na seção §17.7, é necessário um pouco de gambiarra para importar suas chaves para o Bitcoin Core. ## O Que Vem Depois? -Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.3: Usando o BIP32 no Libwally](16_3_Using_BIP32_in_Libwally.md). \ No newline at end of file +Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§17.3: Usando o BIP32 no Libwally](16_3_Using_BIP32_in_Libwally.md). \ No newline at end of file From b139a7611e40e5f5fe3432c946a59eec2a18e6d4 Mon Sep 17 00:00:00 2001 From: namcios Date: Tue, 24 Aug 2021 08:11:44 -0300 Subject: [PATCH 10/14] Review 17_3 --- pt/17_3_Using_BIP32_in_Libwally.md | 38 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/pt/17_3_Using_BIP32_in_Libwally.md b/pt/17_3_Using_BIP32_in_Libwally.md index 040cae3..46749c8 100644 --- a/pt/17_3_Using_BIP32_in_Libwally.md +++ b/pt/17_3_Using_BIP32_in_Libwally.md @@ -1,14 +1,14 @@ -# 16.3: Usando o BIP32 no Libwally +# 17.3: Usando o BIP32 na Libwally > :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. -Na seção [§16.2](16_2_Using_BIP39_in_Libwally.md), fomos capazes de usar a entropia para gerar uma semente e nosso mnemônico relacionado. Como devemos nos lembrar da seção [§3.5: Compreendendo o descritor](03_5_Understanding_the_Descriptor.md), uma seed é a base de uma Carteira Determinística Hierárquica (no inglês Hierchical Deterministic, HD), onde aquela única seed pode ser usada para gerar muitos endereços. Então, como passamos da seed para os endereços reais? É aí que entra o [BIP32](https://en.bitcoin.it/wiki/BIP_0032). +Na seção [§17.2](17_2_Using_BIP39_in_Libwally.md), fomos capazes de usar entropia para gerar uma semente e nosso mnemônico relacionado. Como devemos nos lembrar da seção [§3.5: Compreendendo o Descritor](03_5_Understanding_the_Descriptor.md), uma seed é a base de uma Carteira Determinística Hierárquica (no inglês Hierchical Deterministic, HD), onde aquela única seed pode ser usada para gerar muitos endereços. Então, como passamos da seed para os endereços reais? É aí que entra o [BIP32](https://en.bitcoin.it/wiki/BIP_0032). -## Criando uma raiz HD +## Criando uma Raiz HD Para criar um endereço HD, é necessário começar com uma seed e, em seguida, descer na hierarquia até o ponto em que criamos os endereços. -Isso começa com bastante facilidade, conosco gerando uma seed, o que já fizemos na seção anterior: +Isso começa com bastante facilidade, gerando uma seed, o que já fizemos na seção anterior: ``` unsigned char entropy[16]; randombytes_buf(entropy, 16); @@ -20,7 +20,7 @@ Isso começa com bastante facilidade, conosco gerando uma seed, o que já fizemo size_t seed_len; lw_response = bip39_mnemonic_to_seed(mnem,NULL,seed,BIP39_SEED_LEN_512,&seed_len); ``` -### Gerando uma chave raiz +### Gerando uma Chave Raiz Com uma seed em mãos, podemos gerar uma chave mestra estendida com a função `bip32_key_from_seed_alloc` (ou, alternativamente, com o comando `bip32_key_from_seed`, que não faz o `alloc`): ``` @@ -42,15 +42,15 @@ Sempre que tivermos uma chave em mãos, podemos transformá-la em chaves xpub ou lw_response = bip32_key_to_base58(key_root, BIP32_FLAG_KEY_PUBLIC, &xpub); ``` -## Compreendendo a hierarquia +## Compreendendo a Hierarquia -Antes de prosseguir, precisamos entender como funciona a hierarquia de uma carteira HD. Conforme discutido na seção [§3.5](03_5_Understanding_the_Descriptor.md), um caminho de derivação descreve a árvore que seguimos para obter uma chave hierárquica, então `[0/1/0]` é o 0º filho do 1º filho do 0º filho de uma chave raiz. Às vezes, parte dessa derivação é marcada com `'` s ou `h`s para mostrar derivações endurecidas, que aumentam a segurança: `[0'/1'/0']`. +Antes de prosseguir, precisamos entender como funciona a hierarquia de uma carteira HD. Conforme discutido na seção [§3.5](03_5_Understanding_the_Descriptor.md), um caminho de derivação descreve a árvore que seguimos para obter uma chave hierárquica, então `[0/1/0]` é o 0º filho do 1º filho do 0º filho de uma chave raiz. Às vezes, parte dessa derivação é marcada com `'`s ou `h`s para mostrar derivações endurecidas, que aumentam a segurança: `[0'/1'/0']`. No entanto, para carteiras HD, cada um desses níveis da hierarquia é usado de uma forma muito específica. Isso foi definido originalmente no [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) e foi atualizado posteriormente para o Segwit no [BIP84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki). Ao todo, um caminho de derivação BIP32 é definido para ter cinco níveis: -1. **Objetivo.** Isso geralmente é definido como `44'` ou `84'`, dependendo do BIP que estamos seguindo; +1. **Propósito.** Isso geralmente é definido como `44'` ou `84'`, dependendo do BIP que estamos seguindo; 2. **Moeda.** Para bitcoins Mainnet, é `0'`, para testnet é `1'`; 3. **Conta.** Uma carteira pode conter várias contas discretas, começando com `0'`; 4. **Troco.** Os endereços externos (para distribuição) são definidos como `0`, enquanto os endereços internos (para troco) são definidos como `1`; @@ -62,13 +62,13 @@ Então, na testnet, o endereço zero para um endereço externo para a conta zero ### Entendendo a Hierarquia no Bitcoin Core -Estaremos usando a hierarquia acima para todas as chaves de HD na Libwally, mas observe que este padrão não é usado no `bitcoin-cli` do Bitcoin Core, que ao invés disso usa `[m/0'/0'/0']` para o enésimo endereço externo e `[m/0'/1'/0']` para o enésimo endereço de troco. +Estaremos usando a hierarquia acima para todas as chaves HD na Libwally, mas observe que este padrão não é usado no `bitcoin-cli` do Bitcoin Core, que ao invés disso usa `[m/0'/0'/0']` para o enésimo endereço externo e `[m/0'/1'/0']` para o enésimo endereço de troco. -## Gerando um endereço +## Gerando um Endereço Para gerar um endereço, devemos explorar toda a hierarquia. -### Gerando uma chave da conta +### Gerando uma Chave de Conta Uma maneira de fazer isso é usar a função `bip32_key_from_parent_path_alloc` para descer vários níveis de uma hierarquia. Podemos incorporar os níveis em uma matriz: ``` @@ -87,7 +87,7 @@ Sempre que tiviermos uma nova chave, poderemos usá-la para gerar novas chaves x lw_response = bip32_key_to_base58(key_account, BIP32_FLAG_KEY_PUBLIC, &a_xpub); ``` -### Gerando uma chave de endereço +### Gerando uma Chave de Endereço Alternativamente, podemos usar a função `bip32_key_from_parent_alloc`, que apenas desce um nível da hierarquia por vez. O exemplo a seguir desce para o enésimo filho da chave da conta (que é o endereço externo) e, em seguida, o enésimo filho dessa chave. Isso seria útil porque poderíamos continuar gerando o primeiro endereço, o segundo endereço e assim por diante a partir dessa chave externa: ``` @@ -99,9 +99,9 @@ Alternativamente, podemos usar a função `bip32_key_from_parent_alloc`, que ape ``` > :warning: **AVISO:** Em algum ponto desta hierarquia, podemos decidir gerar o `BIP32_FLAG_KEY_PUBLIC` ao invés do `BIP32_FLAG_KEY_PRIVATE`. Obviamente, essa decisão será baseada na nossa segurança e nas nossas necessidades, mas precisamos lembrar de que só precisamos de uma chave pública para gerar o endereço real. -### Gerando um endereço +### Gerando um Endereço -Finalmente, estamos pronto para gerar um endereço a partir de sua chave final. Tudo que fazemos é executar `wally_bip32_to_addr_segwit` usando nossa chave final e uma descrição de que tipo de endereço é este. +Finalmente, estamos prontos para gerar um endereço a partir de sua chave final. Tudo que fazemos é executar `wally_bip32_to_addr_segwit` usando nossa chave final e uma descrição de que tipo de endereço é este. ``` char *segwit; lw_response = wally_bip32_key_to_addr_segwit(key_address,"tb",0,&segwit); @@ -115,7 +115,7 @@ Há também uma função `wally_bip32_key_to_address`, que pode ser usada para g ## Testando o Código HD -O código para esses exemplos de HD pode, como de costume, ser encontrado no [diretório src/](src / 16_3_genhd.c). +O código para esses exemplos HD pode, como de costume, ser encontrado no [diretório src/](src/17_3_genhd.c). Podemos compilá-lo e testá-lo: ``` @@ -129,14 +129,14 @@ Account xpub key: tpubDWFQG78gYHzCkACXxkeh2LwWo8MVLm3YkTGd85LJwtpBB6xp4KwseGTEvx [m/84'/1'/0'/0/0]: tb1q0knqq26ek59pfl7nukzqr28m2zl5wn2f0ldvwu ``` -## Resumo: Usando o BIP32 no Libwally +## Resumo: Usando o BIP32 na Libwally -Uma carteira HD permite gerar um grande número de chaves a partir de uma única seed. Agora sabemos como essas chaves são organizadas no BIP44, BIP84 e no Bitcoin Core e, como derivá-las, começando com uma seed ou palavras mnemônicas. +Uma carteira HD permite gerar um grande número de chaves a partir de uma única seed. Agora sabemos como essas chaves são organizadas no BIP44, BIP84 e no Bitcoin Core, além de como derivá-las, começando com uma seed ou palavras mnemônicas. > :fire: ***Qual é o poder do BIP32?*** As chaves são o elemento mais difícil (e mais perigoso) da maioria das operações criptográficas. Se as perdermos, perderemos tudo o que a chave protegeu. O BIP32 garante que só precisamos conhecer uma chave, a semente, ao invés de um grande número de chaves diferentes para endereços diferentes. -> :fire: ***Qual é o poder do BIP32 na Libwally?*** O Bitcoind já faz a criação de endereços baseada em HD para nós, o que significa que normalmente não precisamos nos preocupar em derivar endereços dessa maneira. No entanto, usar as funções BIP32 da Libwally pode ser muito útil se estivermos uma máquina offline onde precisamos derivar endereços, possivelmente com base em uma semente passada do `bitcoind` para nosso dispositivo offline (ou vice-versa). +> :fire: ***Qual é o poder do BIP32 na Libwally?*** O Bitcoind já faz a criação de endereços baseada em HD para nós, o que significa que normalmente não precisamos nos preocupar em derivar endereços dessa maneira. No entanto, usar as funções BIP32 da Libwally pode ser muito útil se tivermos uma máquina offline onde precisamos derivar endereços, possivelmente com base em uma semente passada do `bitcoind` para nosso dispositivo offline (ou vice-versa). ## O Que Vem Depois? -Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.4: Usando o PSBTs no Libwally](16_4_Using_PSBTs_in_Libwally.md). \ No newline at end of file +Vamos aprender mais sobre "Programando Bitcoin com Libwally" na seção [§17.4: Usando PSBTs na Libwally](16_4_Using_PSBTs_in_Libwally.md). \ No newline at end of file From 30e32c9449808434b9e6b6d66243f75284d98100 Mon Sep 17 00:00:00 2001 From: namcios Date: Tue, 24 Aug 2021 08:30:52 -0300 Subject: [PATCH 11/14] Review 17_4 --- pt/17_4_Using_PSBTs_in_Libwally.md | 42 ++++++++++++++---------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/pt/17_4_Using_PSBTs_in_Libwally.md b/pt/17_4_Using_PSBTs_in_Libwally.md index efc9b3b..4bff407 100644 --- a/pt/17_4_Using_PSBTs_in_Libwally.md +++ b/pt/17_4_Using_PSBTs_in_Libwally.md @@ -1,10 +1,10 @@ -# 16.4: Usando o PSBTs na Libwally +# 17.4: Usando PSBTs na Libwally > :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. -Nós aprendemos tudo sobre as transações do Bitcoin parcialmente assinadas (PSBTs) na seção [§7.1](07_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md) e na [§7.2](07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md), e como vimos na [§7.3: Integrando com Hardware Wallets](/github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/07_3_Integrating_with_Hardware_Wallets.md), uma das nossas principais vantagens é a capacidade de integração com nodes offline, como Hardware Wallets. O HWI permitiu que passassemos comandos para uma carteira de hardware, mas o que a própria carteira usa para gerenciar os PSBTs? Por acaso, podemos usar algo na Libwally, como esta seção irá demonstrar. +Nós aprendemos tudo sobre as transações parcialmente assinadas no Bitcoin (PSBTs) na seção [§7.1](07_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md) e na [§7.2](07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md), e como vimos na [§7.3: Integrando com Hardware Wallets](/github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/07_3_Integrating_with_Hardware_Wallets.md), uma das nossas principais vantagens é a capacidade de integração com nodes offline, como Hardware Wallets. O HWI permitiu que passássemos comandos para uma carteira de hardware, mas o que a própria carteira usa para gerenciar os PSBTs? Por acaso, podemos usar algo na Libwally, como esta seção irá demonstrar. -Basicamente, a Libwally tem todas as funcionalidades PSBT, então se há algo que podemos fazer com o `bitcoind`, também podemos fazer usando a Libwally, mesmo se nosso dispositivo estiver offline. O que se iremos fazer agora, é a introdução a um tópico bem complexo. +Basicamente, a Libwally tem todas as funcionalidades PSBT, então se há algo que podemos fazer com o `bitcoind`, também podemos fazer usando a Libwally, mesmo se nosso dispositivo estiver offline. O que segue é uma introdução básica a um tópico bem complexo. ## Convertendo um PSBT @@ -14,7 +14,6 @@ Converter um PSBT na estrutura interna da Libwally é incrivelmente fácil, bast No entanto, é um pouco mais difícil de lidar com o resultado, porque a Libwally o converte em uma estrutura `wally_psbt` muito complexa. -Here's how it's defined in `/usr/include/wally_psbt.h`: Veja como é definido no arquivo `/usr/include/wally_psbt.h`: ``` struct wally_psbt { @@ -77,9 +76,9 @@ struct wally_tx_output { ``` Tem muita coisa aí! Embora muito disso deva ser familiar dos capítulos anteriores, é um pouco intimidador ver tudo disposto em estruturas C. -## Lendo um PSBT convertido +## Lendo um PSBT Convertido -Obviamente, podemos ler qualquer coisa de uma estrutura PSBT chamando os elementos individuais das várias subestruturas. A seguir, uma breve visão geral que mostra como captar alguns dos elementos. +Obviamente, podemos ler qualquer coisa de uma estrutura PSBT chamando os elementos individuais das várias subestruturas. A seguir, veja uma breve visão geral que mostra como captar alguns dos elementos. Aqui está um exemplo de recuperação dos valores e os `scriptPubKeys` das entradas: ``` @@ -111,13 +110,13 @@ Aqui está um exemplo semelhante para as saídas: wally_free_string(pubkey_hex); } ``` -Obviamente, há muito mais coisas que poderemos observar nos PSBTs. Na verdade, olhar é o ponto principal de um PSBT: Podemos verificar entradas e saídas de um computador offline. +Obviamente, há muito mais coisas que poderemos observar nos PSBTs. Na verdade, olhar é o ponto principal de um PSBT: podemos verificar entradas e saídas de um computador offline. -> :warning: **AVISO:** Estas funções de leitura são _muito_ rudimentares e não funcionarão corretamente para situações extremamente normais como uma entrada ou saída que ainda está vazia ou que inclui um `non_witness_utxo`. Eles darão um segfault se não forem entregues um PSBT precisamente esperado. Um verdadeiro leitor precisaria ser consideravelmente mais robusto, para cobrir todas as situações possíveis, mas vamos deixar isso para o leitor. +> :warning: **AVISO:** Estas funções de leitura são _muito_ rudimentares e não funcionarão corretamente para situações extremamente normais como uma entrada ou saída que ainda está vazia ou que inclui um `non_witness_utxo`. Elas darão um segfault se não forem entregues um PSBT precisamente esperado. Um leitor de verdade precisaria ser consideravelmente mais robusto, para cobrir todas as situações possíveis, mas vamos deixar isso como um exercício para o leitor. -### Testando nosso leitor PSBT +### Testando Nosso Leitor PSBT -Novamente, o código para este leitor PSBT (extremamente rudimentar e específico) está no [diretório src/](src/16_4_examinepsbt.c). +Novamente, o código para este leitor PSBT (extremamente rudimentar e específico) está no [diretório src/](src/17_4_examinepsbt.c). Podemos compilá-lo normalmente: ``` @@ -146,8 +145,7 @@ scriptPubKey: 0014c772d6f95542e11ef11e8efc7c7a69830ad38a05 INPUT #1 scriptPubKey: 0014f4e8dde5db370898b57c84566e3f76098850817d ``` -And of course, you can check this with the `decodepsbt` RPC command for `bitcoin-cli`: -E, claro, você pode verificar isso com o comando RPC `decodepsbt` para` bitcoin-cli`: +E, claro, você pode verificar tudo isso com o comando RPC `decodepsbt` para` bitcoin-cli`: ``` $ bitcoin-cli decodepsbt $psbt { @@ -264,17 +262,17 @@ $ bitcoin-cli decodepsbt $psbt "fee": 0.00000209 } ``` -Podemos ver a entrada de satoshis e o `scriptPubKey` claramente listadas nos `inputs` e a nova `scriptPubKey` no `vout` do `tx`. +Podemos ver a entrada de satoshis e o `scriptPubKey` claramente listadOs nos `inputs` e a nova `scriptPubKey` no `vout` do `tx`. Então, está tudo lá para utilizarmos! ## Criando um PSBT -Conforme observado no início desta seção, todas as funções necessárias para criar e processar os PSBTs estão disponíveis em Libwally. Na verdade, percorrer todo o processo para fazer isso é complexo o suficiente para estar além do escopo desta seção, mas aqui está um resumo rápido das funções necessárias. Observe que a [documentação](https://wally.readthedocs.io/en/latest/psbt/) está desatualizada para os PSBTs, portanto, precisaremos consultar o `/usr/include/wally_psbt.h` para obter as informações completas. +Conforme observado no início desta seção, todas as funções necessárias para criar e processar os PSBTs estão disponíveis na Libwally. Na verdade, percorrer todo o processo para fazer isso é tão complexo que foge do escopo desta seção, mas aqui está um resumo rápido das funções necessárias. Observe que a [documentação](https://wally.readthedocs.io/en/latest/psbt/) está desatualizada para os PSBTs, portanto, precisaremos consultar o `/usr/include/wally_psbt.h` para obter as informações completas. -Conforme discutido na seção [§7.1](07_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md), existem várias funções envolvidas na criação dos PSBTs. +Conforme discutido na seção [§7.1](07_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md), existem várias funções envolvidas na criação de PSBTs. -### Assumindo o papel de criador +### Assumindo o Papel de Criador A função de criador tem a tarefa de criar um PSBT com pelo menos uma entrada. @@ -289,9 +287,9 @@ Mas o que temos ainda não é um PSBT legal, por falta de entradas. Podemos cri lw_response = wally_tx_init_alloc(0,0,1,1,>x); lw_response = wally_psbt_set_global_tx(psbt,gtx); ``` -### Testando nosso PSBT criado +### Testando nosso PSBT Criado -Neste ponto, devemos ter um PSBT vazio, mas funcionando, que pode ser visto compilando e executando [o programa](src/16_4_createemptypsbt.c). +Neste ponto, devemos ter um PSBT vazio, mas funcionando, que pode ser visto compilando e executando [o programa](src/17_4_createemptypsbt.c). ``` $ cc createemptypsbt.c -lwallycore -o createemptypsbt $ ./createemptypsbt @@ -324,7 +322,7 @@ $ bitcoin-cli decodepsbt $psbt "fee": 0.00000000 } ``` -## Assumindo as demais das funções +## Assumindo as Demais Funções Assim como na leitura de PSBT, estamos introduzindo o conceito de criação do PSBT e, em seguida, deixando o resto como um exercício para o leitor. @@ -367,12 +365,12 @@ A seguir está uma lista aproximada de funções para cada papel. Mais funções * wally_psbt_extract -## Resumo: Usando o PSBTs na Libwally +## Resumo: Usando PSBTs na Libwally Esta seção poderia ser um capítulo inteiro, já que trabalhar com os PSBTs em um nível baixo é um trabalho muito intenso que requer uma manipulação muito mais intensiva de entradas e saídas como foi o caso do [Capítulo 7](07_0_Expanding_Bitcoin_Transactions_PSBTs.md). Ao invés disso, esta seção mostra o básico: como extrair informações de um PSBT e como começar a criar um. -> :fire: ***Qual é o poder dos PSBTs na Libwally?*** Obviamente, já podemos fazer tudo isso nos `bitcoin-cli`, e é mais simples porque o Bitcoin Core gerencia muito do penoso trabalho. A vantagem de usar o Libwally é que ele pode ser executado offline, então pode ser a Libwally que está do outro lado de um dispositivo de hardware com o qual nosso `bitcoin-cli` está se comunicando com o HWI. Este é, de fato, um dos principais pontos dos PSBTs: ser capaz de manipular transações parcialmente assinadas sem a necessidade de um node completo. A Libwally permite isso. +> :fire: ***Qual é o poder dos PSBTs na Libwally?*** Obviamente, já podemos fazer tudo isso nos `bitcoin-cli`, e é mais simples porque o Bitcoin Core gerencia muito do trabalho penoso. A vantagem de usar a Libwally é que ela pode ser executada offline, então pode ser a Libwally que está do outro lado de um dispositivo de hardware com o qual nosso `bitcoin-cli` está se comunicando com o HWI. Este é, de fato, um dos principais pontos dos PSBTs: ser capaz de manipular transações parcialmente assinadas sem a necessidade de um node completo. A Libwally permite isso. ## O Que Vem Depois? -Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.5: Usando Scripts no Libwally](16_5_Using_Scripts_in_Libwally.md). \ No newline at end of file +Vamos aprender mais sobre "Programando Bitcoin com Libwally" na seção [§17.5: Usando Scripts na Libwally](17_5_Using_Scripts_in_Libwally.md). \ No newline at end of file From 7876104d0decbf4184d9a2c2bad9a4e372d2abb4 Mon Sep 17 00:00:00 2001 From: namcios Date: Tue, 24 Aug 2021 08:45:08 -0300 Subject: [PATCH 12/14] Review 17_5 --- pt/17_5_Using_Scripts_in_Libwally.md | 44 ++++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/pt/17_5_Using_Scripts_in_Libwally.md b/pt/17_5_Using_Scripts_in_Libwally.md index 5afb79e..2fb7458 100644 --- a/pt/17_5_Using_Scripts_in_Libwally.md +++ b/pt/17_5_Using_Scripts_in_Libwally.md @@ -1,16 +1,16 @@ -# 16.5: Usando Scripts na Libwally +# 17.5: Usando Scripts na Libwally > :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. -Na seção 3 deste capítulo, ao apresentar os scripts, dissemos que era provável que criássemos transações usando scripts com uma API e dissemos que este era um tópico para o futuro. Bem, o futuro já chegou. +Na seção 3 deste capítulo, ao apresentar os scripts, dissemos que era provável que criássemos transações usando scripts com uma API e dissemos que este era um tópico para o futuro. Bem, agora o futuro chegou. ## Criando o Script -Criar o script é a coisa mais _fácil_ de se fazer na Libwally. Veja o exemplo a seguir, um simples [Puzzle Script](13_1_Writing_Puzzle_Scripts.md) ao qual retornamos de vez em quando: +Criar o script é a coisa _mais fácil_ de se fazer na Libwally. Veja o exemplo a seguir, um simples [Script Quebra-Cabeça](13_1_Writing_Puzzle_Scripts.md) ao qual retornamos de vez em quando: ``` OP_ADD 99 OP_EQUAL ``` -Usando o `btcc`, podemos serializar isso. +Usando o `btcc`, podemos serializar isto. ``` $ btcc OP_ADD 99 OP_EQUAL warning: ambiguous input 99 is interpreted as a numeric value; use 0x99 to force into hexadecimal interpretation @@ -25,7 +25,7 @@ Primeiro, a Libwally precisa converter o hex em bytes, uma vez que os bytes são lw_response = wally_hex_to_bytes(script,bscript,script_length,&written); ``` -Então, executamos o comando `wally_scriptpubkey_p2sh_from_bytes` com os bytes, dizendo a Libwally para também fazer o `HASH160` para nós: +Então, executamos o comando `wally_scriptpubkey_p2sh_from_bytes` com os bytes, dizendo à Libwally para também fazer o `HASH160` para nós: ``` unsigned char p2sh[WALLY_SCRIPTPUBKEY_P2SH_LEN]; @@ -35,11 +35,11 @@ Se olharmos os resultados do `p2sh`, veremos o seguinte: ``` a9143f58b4f7b14847a9083694b9b3b52a4cea2569ed87 ``` -Que [devemos nos lembrar](10_2_Building_the_Structure_of_P2SH.md) de divide em: +Que [devemos nos lembrar](10_2_Building_the_Structure_of_P2SH.md) se divide em: ``` a9 / 14 / 3f58b4f7b14847a9083694b9b3b52a4cea2569ed / 87 ``` -Esse é nosso velho amigo `OP_HASH160 3f58b4f7b14847a9083694b9b3b52a4cea2569ed OP_EQUAL`. +Este é o nosso velho amigo `OP_HASH160 3f58b4f7b14847a9083694b9b3b52a4cea2569ed OP_EQUAL`. Basicamente, a Libwally pegou nosso script de resgate serializado, fez o hash para nós com SHA-256 e RIPEMD-160 e aplicou o enquadramento padrão para transformá-lo em um P2SH adequado. Fizemos um trabalho semelhante ao feito na seção [§10.2](10_2_Building_the_Structure_of_P2SH.md), mas com um excesso de comandos shell. @@ -50,9 +50,9 @@ $ echo -n $redeemScript | xxd -r -p | openssl dgst -sha256 -binary | openssl dgs (stdin)= 3f58b4f7b14847a9083694b9b3b52a4cea2569ed ``` -## Criando uma transação +## Criando uma Transação -A fim de fazer uso do `pubScriptKey` que acabamos de criar, precisamos criar uma transação e incorporar o `pubScriptKey` dentro, e esta é a grande mudança para o `bitcoin-cli`. Podemos criar manualmente uma transação com um script P2SH. +A fim de fazer uso do `pubScriptKey` que acabamos de criar, precisamos criar uma transação e incorporar o `pubScriptKey` dentro dela (e esta é a grande mudança do `bitcoin-cli`: podemos criar manualmente uma transação com um script P2SH). O processo de criação de uma transação na Libwally é muito intenso, assim como o processo de criação de um PSBT, portanto, vamos apenas esboçá-lo, pegando um atalho e, em seguida, deixando um método sem atalhos para investigação futura. @@ -63,7 +63,7 @@ Criar uma transação em si é fácil, só precisamos dizer ao comando `wally_tx ``` Preencher essas entradas e saídas é onde as coisas ficam complicadas! -### Criando uma saída na transação +### Criando uma Saída de Transação Para criar uma saída, dizemos a `wally_tx_output_init_alloc` quantos satoshis estamos gastando, além de entregar o script de bloqueio: ``` @@ -77,9 +77,9 @@ Mais um comando o adiciona à nossa transação: lw_response = wally_tx_add_output(tx,tx_output); ``` -### Criando uma entrada na transação +### Criando uma Entrada de Transação -Criar a entrada é muito mais difícil porque temos que empilhar informações nas rotinas de criação, nem todas as quais são intuitivamente acessíveis quando usamos a Libwally. Então, ao invés de ir mergulhar fundo nessa biblioteca, é neste momento que pegamos nosso atalho. Escrevemos o código de forma que seja passado o código hexadecimal para uma transação que já foi criada e, em seguida, apenas reutilizamos a entrada. +Criar a entrada é muito mais difícil porque temos que empilhar informações nas rotinas de criação, nem todas as quais são intuitivamente acessíveis quando usamos a Libwally. Então, ao invés de mergulharmos fundo nessa biblioteca, é neste momento que pegamos nosso atalho. Escrevemos o código de forma que seja passado o código hexadecimal para uma transação que já foi criada e, em seguida, apenas reutilizamos a entrada. A conversão do código hexadecimal é feita com `wally_tx_from_hex`: ``` @@ -92,27 +92,27 @@ Então podemos roubar as entradas de nosso código hexadecimal para criar uma en lw_response = wally_tx_input_init_alloc(utxo->inputs[0].txhash,sizeof(utxo->inputs[0].txhash),utxo->inputs[0].index,0,utxo->inputs[0].script,utxo->inputs[0].script_len,utxo->inputs[0].witness,&tx_input); assert(lw_response == WALLY_OK); ``` -Como seria de esperar, adicionamos essa entrada à nossa transação: +Como seria de se esperar, adicionamos essa entrada à nossa transação: ``` lw_response = wally_tx_add_input(tx,tx_input); ``` -> **NOTA:** Obviamente, iremos querer criar nossas próprias entradas se estivermos usando Libwally aplicativos reais, mas isso é uma primeira etapa. E, na verdade, pode ser útil para integração com o `bitcoin-cli`, como veremos na seção [§16.7](16_7_Integrating_Libwally_and_Bitcoin-CLI.md). +> **NOTA:** Obviamente, iremos querer criar nossas próprias entradas se estivermos usando Libwally para aplicações reais, mas isso é uma primeira etapa. E, na verdade, pode ser útil para integração com o `bitcoin-cli`, como veremos na seção [§17.7](17_7_Integrating_Libwally_and_Bitcoin-CLI.md). -### Mostrando na tela uma transação +### Vendo uma Transação -Teoricamente, poderíamos assinar e enviar esta transação para nosso programa C construído na Libwally, mas mantendo a ideia de que estamos apenas usando um programa C simples para substituir um P2SH, vamos imprimir o novo hex. Isso é feito com a ajuda de `wally_tx_to_hex`: +Teoricamente, poderíamos assinar e enviar esta transação para nosso programa C construído na Libwally, mas mantendo a ideia de que estamos apenas usando um programa C simples para substituir um P2SH, vamos imprimir o novo hex. Isto é feito com a ajuda de `wally_tx_to_hex`: ``` char *tx_hex; lw_response = wally_tx_to_hex(tx,0, &tx_hex); printf("%s\n",tx_hex); ``` -Mostraremos como fazer uso disso na seção §16.7. +Mostraremos como fazer uso disso na seção §17.7. -## Testando nosso script de substituição +## Testando Nosso Script de Substituição -Podemos pegar o código de teste do [diretório src/](src/16_5_replacewithscript.c) e compilá-lo: +Podemos pegar o código de teste do [diretório src/](src/17_5_replacewithscript.c) e compilá-lo: ``` $ cc replacewithscript.c -lwallycore -o replacewithscript ``` @@ -170,10 +170,10 @@ O `vin` deve apenas corresponder à entrada que substituímos, mas é o `vout` q ## Resumo: Usando Scripts na Libwally -A criação de transações na Libwally é outro tópico que pode ocupar um capítulo inteiro, mas o melhor é que, uma vez que demos esse salto, pode introduzir um P2SH `scriptPubKey`, e só essa parte é muito fácil. Embora a metodologia detalhada neste capítulo exija que já tenhamos um hex de transação em mãos (provavelmente criado com o `bitcoin-cli`) se nos aprofundarmos na Libwally, podemos fazer tudo sozinho. +A criação de transações na Libwally é outro tópico que pode ocupar um capítulo inteiro, mas o melhor é que uma vez que demos esse salto, podemos introduzir um P2SH `scriptPubKey`, e só essa parte é muito fácil. Embora a metodologia detalhada neste capítulo exija que já tenhamos um hex de transação em mãos (provavelmente criado com o `bitcoin-cli`), se nos aprofundarmos na Libwally, podemos fazer tudo sozinhos. -> :fire: ***Qual é o poder dos scripts no Libwally?*** De maneira bem simples, podemos fazer algo que não podíamos antes. Criar uma transação bloqueada com um P2SH arbitrário. +> :fire: ***Qual é o poder dos scripts na Libwally?*** De maneira bem simples, podemos fazer algo que não podíamos antes. Criar uma transação bloqueada com um P2SH arbitrário. ## O Que Vem Depois? -Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.6: Usando Outras Funções no Libwally](16_6_Using_Other_Functions_in_Libwally.md). \ No newline at end of file +Vamos aprender mais sobre "Programando Bitcoin com Libwally" na seção [§17.6: Usando Outras Funções na Libwally](17_6_Using_Other_Functions_in_Libwally.md). \ No newline at end of file From f54d67c5a78aac2157457ec224f976a912cb5acd Mon Sep 17 00:00:00 2001 From: namcios Date: Tue, 24 Aug 2021 08:54:47 -0300 Subject: [PATCH 13/14] Review 17_6 --- pt/17_6_Using_Other_Functions_in_Libwally.md | 59 ++++++++++---------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/pt/17_6_Using_Other_Functions_in_Libwally.md b/pt/17_6_Using_Other_Functions_in_Libwally.md index f198be2..b6f9efe 100644 --- a/pt/17_6_Using_Other_Functions_in_Libwally.md +++ b/pt/17_6_Using_Other_Functions_in_Libwally.md @@ -1,10 +1,10 @@ -# 16.6: Usando Outras Funções no Libwally +# 17.6: Usando Outras Funções na Libwally > :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. -A Libwally é uma extensa biblioteca que fornece uma quantidade considerável de funcionalidades relacionadas à carteira, muitas delas não disponíveis por meio do `bitcoin-cli`. A seguir, está uma visão geral de algumas funcionalidades não abordadas anteriormente neste capítulo. +A Libwally é uma biblioteca extensa que fornece uma quantidade considerável de funcionalidades relacionadas a carteiras, muitas delas não disponíveis por meio do `bitcoin-cli`. A seguir, está uma visão geral de algumas funcionalidades não abordadas anteriormente neste capítulo. -## Usando funções criptográficas +## Usando Funções Criptográficas Diversas funções criptográficas podem ser acessadas diretamente na Libwally: @@ -14,7 +14,7 @@ Diversas funções criptográficas podem ser acessadas diretamente na Libwally: * `wally_scrypt` - Usa derivação de chave Scrypt; * `wally_sha256` - Usa hash SHA256; * `wally_sha256_midstate` - Usa SHA256 para fazer hash apenas do primeiro bloco de dados; - * `wally_sha256d` - Conduza um hash duplo SHA256; + * `wally_sha256d` - Conduz um hash duplo SHA256; * `wally_sha512` - Usa hash SHA512. Existem também funções HMAC para os dois hashes SHA, que são usados ​​para gerar códigos de autenticação de mensagem com base nos hashes. Eles são usados no [BIP32](https://en.bitcoin.it/wiki/BIP_0032), entre outros lugares. @@ -22,30 +22,30 @@ Existem também funções HMAC para os dois hashes SHA, que são usados ​​pa * `wally_hmac_sha256` * `wally_hmac_sha512` -Funções adicionais cobrem derivação chave PBKDF2 e matemática de curva elíptica. +Funções adicionais cobrem derivação de chave PBKDF2 e matemática de curva elíptica. -## Usando funções de endereço +## Usando Funções de Endereço A Libwally contém várias funções que podem ser usadas para importar, exportar e traduzir endereços de Bitcoin. Alguns convertem entre endereços e bytes `scriptPubKey`: - * `wally_addr_segwit_from_bytes` - Converta um programa witness (em bytes) em um endereço Segwit; - * `wally_addr_segwit_to_bytes` - Converta um endereço Segwit em um `scriptPubKey` (em bytes); - * `wally_address_to_scriptpubkey` - Converta um endereço legado em um `scriptPubKey` (em bytes); - * `wally_scriptpubkey_to_address` - Converta um `scriptPubKey` (em bytes) em um endereço legado. + * `wally_addr_segwit_from_bytes` - Converte um programa witness (em bytes) em um endereço Segwit; + * `wally_addr_segwit_to_bytes` - Converte um endereço Segwit em um `scriptPubKey` (em bytes); + * `wally_address_to_scriptpubkey` - Converte um endereço legado em um `scriptPubKey` (em bytes); + * `wally_scriptpubkey_to_address` - Converte um `scriptPubKey` (em bytes) em um endereço legado. Alguns estão relacionados ao formato de importação de carteira (WIF): - * `wally_wif_from_bytes` - Converta uma chave privada (em bytes) para um WIF; + * `wally_wif_from_bytes` - Converte uma chave privada (em bytes) para um WIF; * `wally_wif_is_uncompressed` - Determina se um WIF está descompactado; * `wally_wif_to_address` - Deriva um endereço P2PKH de um WIF; - * `wally_wif_to_bytes` - Converta um WIF em uma chave privada (em bytes); + * `wally_wif_to_bytes` - Converte um WIF em uma chave privada (em bytes); * `wally_wif_to_public_key` - Deriva uma chave pública (em bytes) de um WIF. -## Usando funções BIP32 +## Usando Funções do BIP32 -Existem funções adicionais de carteira HD BIP32, além do que foi abordado na seção [§16.3: Usando o BIP32 no Libwally](16_3_Using_BIP32_in_Libwally.md). +Existem funções adicionais de carteira HD do BIP32, além do que foi abordado na seção [§17.3: Usando o BIP32 na Libwally](17_3_Using_BIP32_in_Libwally.md). * `bip32_key_get_fingerprint` - Gera uma impressão digital BIP32 para uma chave estendida; * `bip32_key_serialize` - Transforma uma chave estendida em bytes serializados; @@ -54,37 +54,36 @@ Existem funções adicionais de carteira HD BIP32, além do que foi abordado na Existem também vários outros comandos, dependendo se desejamos alocar memória ou fazer com que a Libwally faça o `_alloc` para nós. -## Usando funções BIP38 +## Usando Funções do BIP38 -O [BIP38](https://github.com/bitcoin/bips/blob/master/bip-0038.mediawiki) permite a criação de uma chave privada protegida por senha. Não ensinamos porque consideramos perigoso inserir esse tipo de fator humano no gerenciamento de chaves. Se duvida disso, consulte [#SmartCustody](https://www.smartcustody.com/index.html). +O [BIP38](https://github.com/bitcoin/bips/blob/master/bip-0038.mediawiki) permite a criação de uma chave privada protegida por senha. Não o ensinamos porque consideramos perigoso inserir este tipo de fator humano no gerenciamento de chaves. Se duvida disso, consulte [#SmartCustody](https://www.smartcustody.com/index.html). As principais funções são: * `bip38_from_private_key` - Codifica uma chave privada usando BIP38; * `bip38_to_private_key` - Decodifica uma chave privada usando BIP38. -## Usando funções BIP39 +## Usando Funções do BIP39 -Algumas funções de palavras mnemônicas do BIP39 foram resumidas recentemente na seção [§16.2: Usando o BIP39 no Libwally](16_2_Using_BIP39_in_Libwally.md): +Algumas funções de palavras mnemônicas do BIP39 foram resumidas recentemente na seção [§17.2: Usando o BIP39 na Libwally](17_2_Using_BIP39_in_Libwally.md): * `bip39_get_languages` - Veja a lista de idiomas suportados; * `bit39_get_word` - Recupera uma palavra específica da lista de palavras de um idioma; * `bip39_get_wordlist` - Veja uma lista de palavras para um idioma. -## Usando funções PSBT +## Usando Funções de PSBT -As listas da maioria das funções PSBT podem ser encontradas na seção [16.4: Usando o PSBTs no Libwally](16_4_Using_PSBTs_in_Libwally.md). +As listas da maioria das funções de PSBT podem ser encontradas na seção [17.4: Usando PSBTs na Libwally](17_4_Using_PSBTs_in_Libwally.md). -## Usando funções de script +## Usando Funções de Script -A seção [§16.5: Usando Scripts no Libwally](16_5_Using_Scripts_in_Libwally.md) apenas tocou nas funções de scripts da Libwally. +A seção [§17.5: Usando Scripts na Libwally](17_5_Using_Scripts_in_Libwally.md) apenas tocou nas funções de scripts da Libwally. Há outra função que permite determinar o tipo de script encontrado em uma transação: - * `wally_scriptpubkey_get_type` — Determina a transaction's script type; * `wally_scriptpubkey_get_type` - Determina o tipo de script de uma transação. -Depois, há uma série de funções que criam `scriptPubKey` a partir de bytes, o `scriptSig` a partir de assinaturas e witness a partir de bytes ou assinaturas. +Depois, há uma série de funções que criam `scriptPubKey` a partir de bytes, `scriptSig` a partir de assinaturas e Witness a partir de bytes ou assinaturas. * `wally_script_push_from_bytes` * `wally_scriptpubkey_csv_2of2_then_1_from_bytes` @@ -103,7 +102,7 @@ Depois, há uma série de funções que criam `scriptPubKey` a partir de bytes, ## Usando Funções de Transação -Também mal tocamos nas funções que podem ser usadas para criar e converter funções na seção [§16.5](16_5_Using_Scripts_in_Libwally.md). +Também mal tocamos nas funções que podem ser usadas para criar e converter funções na seção [§17.5](17_5_Using_Scripts_in_Libwally.md). Existem inúmeras funções informativas, algumas das mais interessantes são: @@ -113,14 +112,14 @@ Existem inúmeras funções informativas, algumas das mais interessantes são: Também existem funções que afetam um `wally_tx`, um `wally_tx_input`, um `wally_tx_output`, ou um `wally_tx_witness_stack` e que criam assinaturas. -## Usando funções de elementos +## Usando Funções do Elements -A Libwally pode ser compilada para ser usada com os Elementos do Blockstream, que inclui acesso às funções dos ativos. +A Libwally pode ser compilada para ser usada com os Elements da Blockstream, que inclui acesso às funções dos ativos. -## Resumo: Usando Outras Funções no Libwally +## Resumo: Usando Outras Funções na Libwally -Há muito mais coisas que podemos fazer com a Libwally, mais do que podemos abordar neste capítulo ou mesmo listar nesta seção. Notavelmente, podemos executar funções criptográficas, codificar chaves privadas, criar transações completas e usar elementos. A [documentação da Libwally](https://wally.readthedocs.io/en/latest/) é o lugar onde podemos obter mais informações, embora, no momento da criação deste livro, a documentação esteja limitada e desatualizada. Os arquivos de cabeçalho da Libwally são um backup se os documentos estiverem incompletos ou incorretos. +Há muito mais coisas que podemos fazer com a Libwally, mais do que podemos abordar neste capítulo ou mesmo listar nesta seção. Notavelmente, podemos executar funções criptográficas, codificar chaves privadas, criar transações completas e usar Elements. A [documentação da Libwally](https://wally.readthedocs.io/en/latest/) é o lugar onde podemos obter mais informações, embora, no momento da criação deste livro, a documentação esteja limitada e desatualizada. Os cabeçalhos dos arquivos da Libwally são um backup se os documentos estiverem incompletos ou incorretos. ## O Que Vem Depois? -Vamos aprender mais sobre "Programando o Bitcoind usando o Libwally" na seção [§16.7: Integrando o Libwally ao Bitcoin-CLI](16_7_Integrating_Libwally_and_Bitcoin-CLI.md). \ No newline at end of file +Vamos aprender mais sobre "Programando Bitcoin com Libwally" na seção [§17.7: Integrando Libwally e Bitcoin-CLI](17_7_Integrating_Libwally_and_Bitcoin-CLI.md). \ No newline at end of file From 44c594dbdd79b324fb32e98ba115041fd09e0d46 Mon Sep 17 00:00:00 2001 From: namcios Date: Tue, 24 Aug 2021 09:20:05 -0300 Subject: [PATCH 14/14] Review 17_7 --- ..._7_Integrating_Libwally_and_Bitcoin-CLI.md | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/pt/17_7_Integrating_Libwally_and_Bitcoin-CLI.md b/pt/17_7_Integrating_Libwally_and_Bitcoin-CLI.md index b93d537..91c267c 100644 --- a/pt/17_7_Integrating_Libwally_and_Bitcoin-CLI.md +++ b/pt/17_7_Integrating_Libwally_and_Bitcoin-CLI.md @@ -1,14 +1,14 @@ -# 16.7: Integrando o Libwally ao Bitcoin-CLI +# 17.7: Integranda Libwally e Bitcoin-CLI > :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. -A Libwally é limitado. Trata-se de manipular seeds, chaves, endereços e outros elementos de carteiras, com algumas funções adicionais relacionadas a transações e PSBTs que podem ser úteis para serviços que não estão conectados a nodes completos na Internet. No final das contas, no entanto, precisaremos de serviços de nodes completos para aproveitar as vantagens da Libwally. +A Libwally é limitada. Trata-se de manipular seeds, chaves, endereços e outros elementos de carteiras, com algumas funções adicionais relacionadas a transações e PSBTs que podem ser úteis para serviços que não estão conectados a nodes completos na Internet. No final das contas, no entanto, precisaremos de serviços de nodes completos para aproveitar as vantagens da Libwally. -Esta última seção oferecerá alguns exemplos de uso de programas Libwally para complementar um ambiente `bitcoin-cli`. Embora esses exemplos impliquem que esses serviços estão todos na mesma máquina, eles podem se tornar ainda mais poderosos se o serviço `bitcoin-cli` estiver diretamente conectado à internet e o serviço Libwally não. +Esta última seção oferecerá alguns exemplos de uso de programas Libwally para complementar um ambiente `bitcoin-cli`. Embora esses exemplos impliquem que esses serviços estão todos na mesma máquina, eles podem se tornar ainda mais poderosos se o serviço `bitcoin-cli` estiver diretamente conectado à internet e o serviça Libwally não. -## Compartilhando uma transação +## Compartilhando uma Transação -Na seção [§16.5: Usando Scripts no Libwally](16_5_Using_Scripts_in_Libwally.md) detalhamos como a Libwally poderia ser usada para reescrever uma transação existente, para fazer algo que o `bitcoin-cli` não pode, ou seja, produzir uma transação que contém um P2SH único. Obviamente, este é um bloco de construção, se decidirmos nos aprofundar no Libwally, criaremos transações inteiras por conta própria. Mas, esta metodologia abreviada também tem seu próprio uso, mostrar como as transações podem ser passadas de um lado para outro entre `bitcoin-cli` e Libwally, demonstrando um primeiro exemplo de como usá-los de forma complementar. +Na seção [§17.5: Usando Scripts na Libwally](17_5_Using_Scripts_in_Libwally.md) detalhamos como a Libwally poderia ser usada para reescrever uma transação existente, para fazer algo que o `bitcoin-cli` não pode, ou seja, produzir uma transação que contém um P2SH único. Obviamente, esta é uma parte essencial, mas não o todo; se você decidir se aprofundar na Libwally, poderá criar transações inteiras por conta própria. Mas esta metodologia abreviada também tem seu próprio uso, mostrar como as transações podem ser passadas de um lado para outro entre `bitcoin-cli` e Libwally, demonstrando um primeiro exemplo de como usá-los de forma complementar. Para demonstrar totalmente essa metodologia, criaremos uma transação com o `bitcoin-cli`, usando este UTXO: ``` @@ -33,7 +33,7 @@ $ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[0] | .vout') $ recipient=tb1qycsmq3jas5wkhf8xrfn8k7438cm5pc8h9ae2k0 $ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.0009 }''') ``` -Embora tenhamos colocado um destinatário e uma quantia na saída, é irrelevante, porque nós o reescreveremos. Um código mais elaborado poderia ler as informações `vout` existentes antes de reescrever, mas estamos mantendo as coisas muito próximas do nosso [código original](src/16_5_replacewithscript.c). +Embora tenhamos colocado um destinatário e uma quantia na saída, isto é irrelevante, porque nós o reescreveremos. Um código mais elaborado poderia ler as informações `vout` existentes antes de reescrever, mas estamos mantendo as coisas muito próximas do nosso [código original](src/17_5_replacewithscript.c). Aqui está a única alteração necessária, para permitir que especifiquemos os satoshis no `vout`, sem ter que codificá-lo, como no original: ``` @@ -129,7 +129,7 @@ Depois, podemos assiná-la normalmente com o `bitcoin-cli`: ``` $ signedtx=$(bitcoin-cli signrawtransactionwithwallet $newtxhex | jq -r '.hex') ``` -E como podemos ver, o resultado é uma transação legítima pronta para ir para a rede Bitcoin: +E, como podemos ver, o resultado é uma transação legítima pronta para ir para a rede Bitcoin: ``` $ bitcoin-cli decoderawtransaction $signedtx { @@ -170,21 +170,21 @@ $ bitcoin-cli decoderawtransaction $signedtx ``` Pronto! Esse é o poder da Libwally com o `bitcoin-cli`. -Obviamente, também pode passar um PSBT usando as funções descritas na seção [§16.4](16_4_Using_PSBTs_in_Libwally.md) e essa é uma metodologia mais atualizada para o uso moderno do Bitcoin, mas em qualquer um dos exemplos, o conceito de passar transações do `bitcoin-cli` para código Libwally e vice-versa deve ser semelhante. +Obviamente, também podemos passar um PSBT usando as funções descritas na seção [§17.4](17_4_Using_PSBTs_in_Libwally.md) e esta é uma metodologia mais atualizada para o uso moderno do Bitcoin; mas em qualquer um dos exemplos, o conceito de passar transações do `bitcoin-cli` para códiga Libwally e vice-versa deve ser semelhante. -## Importando e exportando seeds BIP39 +## Importando e Exportando Seeds BIP39 -Infelizmente, nem todas as interações entre a Libwally e o `bitcoin-cli` são fáceis. Por exemplo, seria bom se pudessemos exportar uma seed HD do `bitcoin-cli`, para gerar a frase mnemônica com a Libwally, ou gerar uma seed de uma frase mnemônica usando a Libwally e depois importá-la para o `bitcoin-cli `. Infelizmente, nada disso é possível neste momento. Uma frase mneômica é traduzida em uma seed usando HMAC-SHA512, o que significa que o resultado é 512 bits. No entanto, o `bitcoin-cli` exporta seeds HD (usando `dumpwallet`) e importa sementes HD (usando `sethdseed`) com um comprimento de 256 bits. Até que isso seja mudado, não podemos fazer nada sobre isso. +Infelizmente, nem todas as interações entre a Libwally e o `bitcoin-cli` são fáceis. Por exemplo, seria bom se pudéssemos exportar uma seed HD do `bitcoin-cli` para gerar a frase mnemônica com a Libwally, ou gerar uma seed de uma frase mnemônica usando a Libwally e depois importá-la para o `bitcoin-cli `. Infelizmente, nada disso é possível neste momento. Uma frase mneômica é traduzida em uma seed usando HMAC-SHA512, o que significa que o resultado é 512 bits. No entanto, o `bitcoin-cli` exporta seeds HD (usando `dumpwallet`) e importa seeds HD (usando `sethdseed`) com um comprimento de 256 bits. Até que isso seja mudado, não há nada que possamos fazer. -> :book: ***Qual é a diferença entre entropia e uma seed?*** A Libwally diz que criamos nossas frases mnemônicas a partir da entropia. Isso é essencialmente a mesma coisa que uma seed, pois ambos são números grandes e aleatórios. Portanto, se o `bitcoin-cli` fosse compatível com as sementes de frase mnemônica de 512 bits, poderíamos usar uma para gerar as frases mnemônicas e obter os resultados esperados. +> :book: ***Qual é a diferença entre entropia e uma seed?*** A Libwally diz que criamos nossas frases mnemônicas a partir de entropia. Isso é essencialmente a mesma coisa que uma seed, pois ambos são números grandes e aleatórios. Portanto, se o `bitcoin-cli` fosse compatível com as seeds de frase mnemônica de 512 bits, poderíamos usar uma para gerar as frases mnemônicas e obter os resultados esperados. -> :book: ***Qual é a diferença entre entropia e entropia bruta?*** Nem toda entropia é a mesma. Quando inserimos entropia em um comando que cria uma seed mnemônica, ela tem um comprimento específico e bem conhecido. Mudar a entropia bruta em uma entropia requer alterar a entropia bruta até que tenha o comprimento e o formato corretos, e nesse ponto podemos reutilizar essa entropia (não bruta) para sempre recriar os mesmos mnemônicos (razão pela qual a entropia é efetivamente a mesma coisa que um seed naquele ponto, mas a entropia bruta não). +> :book: ***Qual é a diferença entre entropia e entropia bruta?*** Nem toda entropia é a mesma. Quando inserimos entropia em um comando que cria uma seed mnemônica, ela tem um comprimento específico e bem conhecido. Mudar de entropia bruta para entropia requer alterar a entropia bruta até que se tenha o comprimento e o formato corretos, e nesse ponto podemos reutilizar essa entropia (não bruta) para sempre recriar os mesmos mnemônicos (razão pela qual a entropia é efetivamente a mesma coisa que uma seed naquele ponto, mas a entropia bruta não). -## Importando chaves privadas +## Importando Chaves Privadas -Felizmente, podemos fazer quase a mesma coisa importando uma chave privada gerada na Libwally. Dê uma olhada no [genhd-for-import.c](src/16_7_genhd_for_import.c), uma versão simplificada do programa `genhd` da seção [§16.3](16_3_Using_BIP32_in_Libwally.md) que também usa a biblioteca `jansson` da seção [ §15.1](15_1_Accessing_Bitcoind_with_C.md) para saída regularizada. +Felizmente, podemos fazer quase a mesma coisa importando uma chave privada gerada na Libwally. Dê uma olhada no [genhd-for-import.c](src/17_7_genhd_for_import.c), uma versão simplificada do programa `genhd` da seção [§17.3](17_3_Using_BIP32_in_Libwally.md) que também usa a biblioteca `jansson` da seção [§16.1](16_1_Accessing_Bitcoind_with_C.md) para saída regularizada. -O código atualizado também contém uma alteração importante, pois ele solicita uma impressão digital da Libwally para que possa criar um caminho de derivação de maneira adequada: +O código atualizado também contém uma alteração importante, pois ele solicita uma impressão digital da Libwally para que se possa criar um caminho de derivação de maneira adequada: ``` char account_fingerprint[BIP32_KEY_FINGERPRINT_LEN]; lw_response = bip32_key_get_fingerprint(key_account,account_fingerprint,BIP32_KEY_FINGERPRINT_LEN); @@ -193,13 +193,13 @@ O código atualizado também contém uma alteração importante, pois ele solici lw_response = wally_hex_from_bytes(account_fingerprint,BIP32_KEY_FINGERPRINT_LEN,&fp_hex); ``` -> :aviso: **AVISO:** Lembre-se de que a impressão digital nos caminhos de derivação é arbitrária. Como o Libwally fornece um, nós o estamos usando, mas se não tivermos um, poderemos adicionar um código hexadecimal arbitrário de 4 bytes como uma impressão digital em nosso caminho de derivação. +> :aviso: **AVISO:** Lembre-se de que a impressão digital nos caminhos de derivação é arbitrária. Como a Libwally fornece um, nós o estamos usando, mas se não tivéssemos um, poderíamos adicionar um código hexadecimal arbitrário de 4 bytes como uma impressão digital em nosso caminho de derivação. -Certifique-se de compilar o novo código com a biblioteca `jansson`, após instalá-lo (se necessário) de acordo com a seção [§15.1](15_1_Accessing_Bitcoind_with_C.md). +Certifique-se de compilar o novo código com a biblioteca `jansson`, após instalá-lo (se necessário) de acordo com a seção [§16.1](16_1_Accessing_Bitcoind_with_C.md). ``` $ cc genhd-for-import.c -lwallycore -lsodium -ljansson -o genhd-for-import ``` -Quando executamos o novo programa, ele nos dará uma lista de saída com todas as informações: +Quando executarmos o novo programa, ele nos dará uma lista de saída com todas as informações: ``` $ ./genhd-for-import { @@ -209,11 +209,11 @@ $ ./genhd-for-import "derivation": "[d1280779/84h/1h/0h]" } ``` -Temos o `mnemônico` que podemos recuperar, um `account-xprv` que podemos importar, uma `derivação` para usar para a importação e um `address` de amostra, que podemos usar para testar a importação. +Temos o `mnemonic` que podemos recuperar, um `account-xprv` que podemos importar, uma `derivation` para usar para a importação e um `address` de amostra, que podemos usar para testar a importação. Agora podemos recorrer às lições aprendidas na seção [§3.5](03_5_Understanding_the_Descriptor.md) sobre como transformar esse xprv em um descritor e importá-lo. -Primeiro, precisamos descobrir a soma de verificação: +Primeiro, precisamos descobrir o checksum: ``` $ xprv=tprv8yxn8iFNgsLktEPkWKQpMqb7bcx5ViFQEbJMtqrGi8LEgvy8es6YeJvyJKrbYEPKMw8JbU3RFhNRQ4F2pataAtTNokS1JXBZVg62xfd5HCn $ dp=[d1280779/84h/1h/0h] @@ -229,7 +229,7 @@ $ bitcoin-cli getdescriptorinfo "wpkh($dp$xprv/0/*)" Há três coisas a serem observadas aqui: -1. Usamos o `wpkh` como a função em nosso caminho de derivação. Isso porque queremos gerar endereços Segwit modernos, não endereços legados. Isso corresponde ao uso na Libwally da função `wally_bip32_key_to_addr_segwit`. A coisa mais importante, entretanto, é ter as mesmas expectativas com a Libwally e o `bitcoin-cli` (e nosso descritor) de que tipo de endereço estamos gerando, para que tudo sê certo; +1. Usamos o `wpkh` como a função em nosso caminho de derivação. Isso porque queremos gerar endereços Segwit modernos, não endereços legados. Isso corresponde ao uso na Libwally da função `wally_bip32_key_to_addr_segwit`. A coisa mais importante, entretanto, é ter as mesmas expectativas com a Libwally e o `bitcoin-cli` (e nosso descritor) de que tipo de endereço estamos gerando, para que tudo dê certo; 2. Usamos o caminho `/0/*` porque queríamos os endereços externos para esta conta. Se, em vez disso, quiséssemos alterar os endereços, usaríamos `/1/*`; 3. Não vamos usar a linha `descriptor` que foi retornada, pois é para um endereço `xpub`. Ao invés disso, aplicaremos o `checksum` retornado ao `xprv` que já temos. ``` @@ -247,7 +247,7 @@ $ bitcoin-cli importmulti '''[{ "desc": "wpkh('$dp''$xprv'/0/*)#'$cs'", "timesta ``` Aqui, importamos/geramos os primeiros dez endereços para a chave privada. -Vamos examinar o novo rótulo `LibwallyImported`: +Vamos examinar o novo rótulo `LibwallyImports`: ``` $ bitcoin-cli getaddressesbylabel "LibwallyImports" { @@ -289,15 +289,15 @@ $ bitcoin-cli getaddressesbylabel "LibwallyImports" ``` O segundo em nossa lista realmente corresponde ao que temos de amostra (`tb1q9lhru6k0ymwrtr5w98w35n3lz22upml23h753n`). A importação desta chave privada e a derivação de dez endereços foram bem-sucedidas. -Se olharmos agora para trás na seção [§7.3](07_3_Integrating_with_Hardware_Wallets.md), veremos que esta era a mesma metodologia que usamos para importar endereços de uma carteira física (embora desta vez também importamos a chave privada como prova de conceito). A maior diferença é que anteriormente a informação era criada por uma caixa preta (literalmente, pois era um dispositivo Ledger), e desta vez nós mesmos criamos a informação usando a Libwally, mostrando como podemos fazer esse tipo de trabalho de maneira airgaped ou em outro dispositivo remoto e, em seguida, levá-lo ao `bitcoin-cli`. +Se olharmos agora para trás na seção [§7.3](07_3_Integrating_with_Hardware_Wallets.md), veremos que esta era a mesma metodologia que usamos para importar endereços de uma hardware wallet (embora desta vez também importamos a chave privada como prova de conceito). A maior diferença é que anteriormente a informação era criada por uma caixa preta (literalmente: era um dispositivo Ledger), e desta vez nós mesmos criamos a informação usando a Libwally, mostrando como podemos fazer esse tipo de trabalho de maneira airgaped ou em outro dispositivo remoto e, em seguida, levá-lo ao `bitcoin-cli`. -## Importando endereços +## Importando Endereços Obviamente, se podemos importar chaves privadas, também podemos importar endereços, o que geralmente significa importar endereços somente para observação _sem_ as chaves privadas. -Uma maneira do fazer isso é utilizar a metodologia `importmulti` acima, mas neste caso, usamos o endereço fornecido XPUB (`wpkh([d1280779/84'/1'/0']tpubDWepH8HcqF2RmhRYPy5QmFFEAeU1f3SJotu9BMta8Q8dXRDuHFv8poYqUUtEiWftBjtKn1aNhi9Qg2P4NdzF66dShYvB92z78WJbYeHTLTz/0/*)#f8rmqc0z`) ao invés do xprv original. Essa é a melhor maneira de importar uma sequência inteira de endereços somente para observação. +Uma maneira de fazer isso é utilizar a metodologia `importmulti` acima, mas neste caso, usamos o endereço xpub fornecido (`wpkh([d1280779/84'/1'/0']tpubDWepH8HcqF2RmhRYPy5QmFFEAeU1f3SJotu9BMta8Q8dXRDuHFv8poYqUUtEiWftBjtKn1aNhi9Qg2P4NdzF66dShYvB92z78WJbYeHTLTz/0/*)#f8rmqc0z`) ao invés do xprv original. Essa é a melhor maneira de importar uma sequência inteira de endereços somente para observação. -Como alternativa, podemos importar endereços individuais. Por exemplo, considere o único endereço de amostra retornado pelo programa `genhd-for-import`: +Como alternativa, podemos importar endereços individuais. Por exemplo, considere o único endereço de amostra retornado pelo programa `genhd-for-import`: ``` $ ./genhd-for-import { @@ -319,12 +319,12 @@ $ bitcoin-cli getaddressesbylabel "LibwallyWO" } ``` -## Resumo: Integrando o Libwally ao Bitcoin-CLI +## Resumo: Integrando Libwally e Bitcoin-CLI -Com um conhecimento básico de Libwally, agora podemos complementar todo o trabalho das lições anteriores. A transferência de endereços, chaves, transações e PSBTs são apenas algumas das maneiras pelas quais podemos usar esses dois poderosos métodos de programação do Bitcoin juntos. Também há muito mais profundidade potencial se quisermos nos aprofundar na extensa biblioteca de funções do Libwally. +Com um conhecimento básico de Libwally, agora podemos complementar todo o trabalho das lições anteriores. A transferência de endereços, chaves, transações e PSBTs são apenas algumas das maneiras pelas quais podemos usar esses dois poderosos métodos de programação do Bitcoin juntos. Também há muito mais profundidade potencial se quisermos nos aprofundar na extensa biblioteca de funções da Libwally. -> :fire: ***Qual é o poder de integrar Libwally e Bitcoin-CLI?*** Uma das maiores vantagens do Libwally é que ele tem muitas funções que podem ser usadas offline. Em comparação, o Bitcoin Core é um programa em rede. Isso pode ajudá-lo a aumentar a segurança fazendo com que o `bitcoin-cli` passe chaves, endereços, transações ou PSBTs para uma fonte offline (que estaria executando programas Libwally). Além disso, o Libwally pode fazer coisas que o Bitcoin Core não pode, como gerar uma seed a partir de um mnemônico BIP39 (e mesmo se não pudermos importá-la para o Bitcoin Core, _podemos_ importar a chave mestra, conforme mostrado aqui). +> :fire: ***Qual é o poder de integrar Libwally e Bitcoin-CLI?*** Uma das maiores vantagens da Libwally é que ela tem muitas funções que podem ser usadas offline. Em comparação, o Bitcoin Core é um programa em rede. Isso pode ajudá-lo a aumentar a segurança fazendo com que o `bitcoin-cli` passe chaves, endereços, transações ou PSBTs para uma fonte offline (que estaria executando programas Libwally). Além disso, a Libwally pode fazer coisas que o Bitcoin Core não pode, como gerar uma seed a partir de um mnemônico BIP39 (e mesmo se não pudermos importá-la para o Bitcoin Core, _podemos_ importar a chave mestra, conforme mostrado aqui). ## O Que Vem Depois? -Saiba mais sobre outras linguagens de programação no [Capítulo 17: Conversando com o Bitcoind com Outras Linguagens](17_0_Talking_to_Bitcoind_Other.md). \ No newline at end of file +Saiba mais sobre outras linguagens de programação no [Capítulo 18: Conversando com o Bitcoind com Outras Linguagens](18_0_Talking_to_Bitcoind_Other.md). \ No newline at end of file