Merge pull request #550 from BlockchainCommons/portuguese-translation

Merge Portuguese translation v2.0.1
This commit is contained in:
Shannon Appelcline 2021-11-09 08:31:17 -10:00 committed by GitHub
commit ec887633eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
103 changed files with 17821 additions and 0 deletions

63
pt/01_0_Introduction.md Normal file
View File

@ -0,0 +1,63 @@
# Capítulo 1: Introdução à Aprendizagem do Bitcoin Core (& Lightning) pela Linha de Comando
## Introdução
Os modos como fazemos pagamentos por bens e serviços têm mudado drasticamente nas últimas décadas. Antigamente todas as transações eram realizadas utilizando dinheiro ou cheques, e atualmente os diversos métodos de pagamento eletrônico são à regra. Porém, a maioria dos pagamentos eletrônicos ainda ocorre utilizando sistemas centralizados, onde empresas de cartão de crédito, bancos ou até instituições financeiras baseadas apenas na Internet, como o PayPal, mantêm listas de transações longas e correlacionadas individualmente, tendo o poder de censurar as transações que não gostarem.
Esses riscos de centralização foram alguns dos catalisadores primordiais para a criação de criptomoedas, sendo a primeira e mais bem sucedida, o Bitcoin. O Bitcoin oferece pseudonímia; torna difícil correlacionar as transações; e torna a censura por entidades individuais, algo próximo do impossível. Essas vantagens fizeram dele uma das moedas mais rápidas do mundo. Esse crescimento, por sua vez, despertou o interesse dos empresários e desenvolvedores, ansiosos para criar novos serviços para a comunidade do Bitcoin.
Se você é um desses empreendedores ou desenvolvedores, então este curso é para você, porque ele tem tudo o que necessita para aprender a programar no Bitcoin. É um curso introdutório que explica todas as nuances e características do Bitcoin e de tudo o que vem com ele. O curso também oferece algumas coisas mais específicas, como aulas de como utilizar _diretamente_ o Bitcoin Core com o servidor C-Lightning usando suas interfaces RPC.
Por que não utilizar algumas das bibliotecas mais detalhadas encontradas em várias linguagens de programação? Por que não criar a sua própria do zero? Porque trabalhar com criptomoedas é perigoso. Não há redes de segurança. Se você acidentalmente pagar taxas muito altas ou perder uma chave de assinatura ou criar uma transação inválida ou fazer qualquer outros milhares de erros potenciais, você dará adeus a suas moedas para sempre. Muito dessa responsabilidade, é claro, fica com você como sendo um programador de criptomoedas, mas também pode ser minimizado, trabalhando com as interfaces de criptomoedas mais robustas e seguras que estão disponíveis, as que foram criadas pelas próprias equipes de programação dessas criptomoedas: A ``Bitcoind`` e a ``Lightningd``.
Grande parte deste livro discute como fazer um script em bitcoin (e na Lightning Network) diretamente pela linha de comando. Alguns capítulos adiantes lidam com linguagens de programação mais sofisticadas, mas novamente continuam a interagir diretamente com o `` Bitcoind`` e a ``Lightningd``, usando o RPC ou interagindo com os arquivos que são criados por eles. Isso permite que você se mantenha no mesmo nível dos gigantes e use a tecnologia confiável para aprender como criar seus próprios sistemas confiáveis.
## Nível de Habilidade Necessária
Você não precisa ser particularmente uma pessoa da área técnica para boa parte deste curso. Tudo o que precisará é a confiança para executar comandos básicos pela linha de comando do UNIX. Se você está familiarizado com coisas como ``ssh``, ``cd``, e ``ls``, o curso irá te fornecer o resto.
Uma minoria deste curso requer conhecimento de programação, e você deve pular essas seções, se necessário, conforme iremos discutir na próxima seção.
## Resumo dos Tópicos
Este livro é dividido nas seguintes seções:
| Parte | Descrição | Habilidades |
|-------|---------|---------|
| **Parte Um: Se Preparando para o Bitcoin** | Entendendo os fundamentos do Bitcoin e configurando um servidor para uso. | Linha de Comando |
| **Parte Dois: Usando o Bitcoin-CLI** | Usando o Bitcoin-CLI para criar transações. | Linha de Comando |
| **Parte Três: Programando no Bitcoin** | Expandindo nosso trabalho no Bitcoin com scripts. | Conceitos de Programação |
| **Parte Quatro: Privacidade** | Melhorando a segurança do nosso node com Tor ou I2P | Linha de Comando |
| **Parte Cinco: Programando com RPC** | Acessando o RPC com C e outras linguagens. | Programando em C |
| **Parte Seis: Usando a Lightning-CLI** | Usando a Lightning-CLI para criar transações. | Linha de Comando |
| **Apêndices.** | Utilizando configurações incomuns no Bitcoin. | Linha de Comando |
## Como Usar Este Curso
Então, por onde você começa? Este livro é destinado principalmente para ser lido em sequência. Basta seguir o "O que vem depois?" que estarão no final de cada seção e/ou clicar nos links individuais de cada seção em cada página do capítulo. Você conseguirá o melhor entendimento deste curso se realmente se construir um servidor Bitcoin (no capítulo 2) e, em seguida, passar por todos os exemplos que estarão disponíveis ao longo do livro: Testar os exemplos é uma excelente metodologia de aprendizado.
Se você tem diferentes níveis de habilidade ou se quiser aprender coisas diferentes, poderá pular para algumas partes diferentes do livro:
* Se você já tem um ambiente pronto do Bitcoin para ser utilizado, vá para o [Capítulo 3: Compreendendo Nossa Configuração do Bitcoin](03_0_Understanding_Your_Bitcoin_Setup.md).
* Se você só se importa com programar no Bitcoin, pule para o [Capítulo 9: Apresentando os Scripts do Bitcoin](09_0_Introducing_Bitcoin_Scripts.md).
* Se você quiser apenas ler sobre o uso das linguagens de programação, pule para o [Capítulo 16: Conversando com o Bitcoind com C](16_0_Talking_to_Bitcoind.md).
* Se não quer programar nada, definitivamente ignore os capítulos 16 ao 18 enquanto estiver lendo, e talvez seja melhor pular os capítulos 9 ao 13. O resto do curso ainda deve fazer sentido sem eles.
* Se estiver interessado apenas na Lightning Network, corra para o [Capítulo 19: Compreendendo Nossa Configuração da Lightning](19_0_Understanding_Your_Lightning_Setup.md).
* Se quiser ler o conteúdo novo adicionado na versão 2 do curso (2020), seguido da versão 1 (2017), leia [§3.5: Entendendo o Descritor](03_5_Understanding_the_Descriptor.md), [§4.6: Criando uma Transação SegWit](04_6_Creating_a_Segwit_Transaction.md), [Capítulo 7: Expandindo Transações no Bitcoin com PSBTs](07_0_Expanding_Bitcoin_Transactions_PSBTs.md), [§9.5: Programando um P2WPKH](09_5_Scripting_a_P2WPKH.md), [§10.5: Programando um Script SegWit](10_5_Scripting_a_Segwit_Script.md), [Capítulo 14: Usando o Tor](14_0_Using_Tor.md), [Capítulo 16: Conversando com o Bitcoind com C](16_0_Talking_to_Bitcoind.md), [Capítulo 17: Programando o Bitcoin com Libwally](17_0_Programming_with_Libwally.md), [Capítulo 18: Conversando com o Bitcoind com Outras Linguagens](18_0_Talking_to_Bitcoind_Other.md), [Capítulo 19: Compreendendo Nossa Configuração da Lightning](19_0_Understanding_Your_Lightning_Setup.md), e [Capítulo 20: Usando a Lightning](20_0_Using_Lightning.md).
## Por Que Utilizar Este Curso
Obviamente, você está querendo fazer este curso porque está interessado no Bitcoin. Além de transmitir o conhecimento básico, também ajudará os leitores a participar (ou criar) projetos open source e obter empregos de cargos júnior na área de programação envolvendo o Bitcoin. Um número de estagiários na Blockchain Commons aprendeu sobre o Bitcoin através deste curso, e muitos dos membros da nossa equipe de programação também.
## Como Ajudar Este Curso
* Por favor, use a área de [Issues](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/issues) para quaisquer dúvidas. A Blockchain Commons não tem uma equipe ativa de suporte, e não podemos abordar problemas ou perguntas individuais, mas iremos tratá-los com o tempo e os usaremos para melhorar nossas futuras iterações no curso.
* Por favor, use os [PRs](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/pulls) para quaisquer correções de erros de digitação ou comandos incorretos (ou que foram alterados). Para alterações técnicas ou de linha de comando, é muito útil se você usar também os comentários para explicar por que fez o que você fez, para que não precisemos gastar tempo pesquisando o motivo.
* Por favor, use nossa [Área de Discussão da Comunidade](https://github.com/BlockchainCommons/Community/discussions) para falar sobre carreiras e habilidades. A Blockchain Commons ocasionalmente oferece estágios, como falado em nosso repositório da comunidade.
* Por favor, [torne-se um patrocinador](https://github.com/sponsors/BlockchainCommons) se achar este curso útil ou se quiser ajudar a educar a próxima geração de programadores da blockchain.
## O Que Vem Depois?
Se você quiser uma introdução básica ao Bitcoin, criptografia de chave pública, ECC, blockchains e Lightning Network, leia o prefácio [Apresentando o Bitcoin](01_1_Introducing_Bitcoin.md).
Caso contrário, se já estiver pronto para mergulhar de cabeça no curso, vá para [Configurando um Bitcoin-Core VPS](02_0_Setting_Up_a_Bitcoin-Core_VPS.md).

View File

@ -0,0 +1,149 @@
# Prefácio: Apresentando o Bitcoin
Antes de começar a programar em Bitcoin (e Lightning), você deve ter uma compreensão básica do que são e como funcionam. Esta seção fornece essa visão geral. Várias outras definições irão aparecer mais à frente. O objetivo deste capítulo é apenas dar o conteúdo base.
## Sobre o Bitcoin
O Bitcoin é um sistema programável que permite a transferência da moeda bitcoin. Tem como base um sistema descentralizado _peer-to-peer_ (de ponta à ponta) de nodes, que inclui full nodes, carteiras e mineradores. Trabalhando juntos, eles garantem que as transações do bitcoin sejam rápidas e irreversíveis. Graças à natureza descentralizada do sistema, essas transações também são resistentes à censura e podem fornecer outras vantagens, como pseudo-anonimato, caso sejam bem utilizadas.
Obviamente, Bitcoin é o coração deste livro, mas também é o originador de muitos outros sistemas, incluindo a blockchain e Lightning, que são detalhados neste tutorial, e muitas outras criptomoedas, como Ethereum e Litecoin, que não são.
**_Como as moedas são transferidas?_** O Bitcoin não possui moedas físicas. Elas são uma série interminável de trocas títulos de propriedade. Quando uma pessoa envia as moedas para outra, essa transferência é armazenada como uma transação. É a transação que realmente registra a propriedade do dinheiro, isso significa que não existe nenhuma moeda que sai da carteira ou da máquina do proprietário.
**_Para quem você pode enviar as moedas?_** A grande maioria das transações de bitcoin envolvem o envio de moedas para pessoas comuns (ou pelo menos para endereços Bitcoin de pessoas comuns). No entanto, metodologias mais complexas podem ser usadas para enviar bitcoins para um grupo de pessoas ou para scripts. Essas várias metodologias possuem nomes como P2PKH, multisig e P2SH.
**_Como as transações são armazenadas?_** As transações são combinadas em grandes blocos de dados, que são gravados na _ledger da blockchain_. Um bloco é construído de tal forma que não pode ser substituído ou reescrito, uma vez que vários blocos tenham sido construídos depois dele. Isso é o que torna os bitcoins irreversíveis: Um livro razão (_ledger_) global descentralizado, onde tudo é registrado, é efetivamente um banco de dados permanente e imutável.
Porém, o processo de construção desses blocos é estocástico: É um tanto aleatório, então não podemos ter certeza se uma transação será colocada em um bloco específico. Também pode haver alterações nos blocos se forem muito recentes, mas apenas se forem _muitíssimo_ recentes. Então, as coisas se tornam irreversíveis (permanentes, imutáveis) depois de um alguns minutos.
**_Como as transações são protegidas?_** Os fundos contidos em uma transação Bitcoin são assegurados por um quebra-cabeça criptográfico. Esses quebra-cabeças são projetados para que possam ser facilmente resolvidos pela pessoa para quem os fundos foram enviados. Isso é feito usando o poder da criptografia de chave pública. Tecnicamente, uma transação é protegida por uma assinatura que prova que você é o proprietário da chave pública para a qual a transação foi enviada: Essa prova de propriedade é o quebra-cabeça que está sendo resolvido.
Os fundos são protegidos pelo uso de hashes. As chaves públicas não são realmente armazenadas na blockchain até que os fundos sejam gastos: Apenas os hashes de chave pública são. Isso significa que, mesmo que um computador quântico seja criado, as transações do Bitcoin permaneceriam protegidas por esse segundo nível de criptografia.
**_Como as transações são criadas?_** O coração de cada transação do Bitcoin é uma linguagem script do tipo FORTH usada para bloquear a transação. Para reenviar o dinheiro, o destinatário fornece informações específicas ao script que prova que ele é o destinatário pretendido.
No entanto, esses scripts do Bitcoin são o nível mais baixo de funcionalidade deste protocolo. Grande parte do trabalho do Bitcoin é feito através do `bitcoind` do Bitcoin, que é controlado por meio de comandos RPC. Muitas pessoas enviam esses comandos RPC por meio do programa chamado `bitcoin-cli`, que fornece uma interface ainda mais simples. Os não programadores nem mesmo se preocupam com essas minúcias, permitindo o uso de carteiras programáveis com interfaces mais simples.
### Bitcoin Em Resumo
Uma maneira de pensar no Bitcoin é como _uma sequência de transações atômicas_. Cada transação é autenticada por um remetente com a solução para um quebra-cabeça criptográfico anterior que foi armazenado como um script. A nova transação é bloqueada para o destinatário com um novo quebra-cabeça criptográfico que também é armazenado como um script. Cada transação é registrada no livro razão global imutável.
## Sobre Criptografia de Chave Pública
A criptografia de chave pública é um sistema matemático para proteção de dados e comprovação de propriedade por meio de um par assimétrico de chaves que estão vinculadas entre si: a chave pública e a chave privada.
É importante para o Bitcoin (e para a maioria dos sistemas que utilizam a blockchain) porque é a base de grande parte da criptografia que protege os fundos das criptomoedas. Uma transação de Bitcoin é normalmente enviada para um endereço que é um hash da chave pública. O destinatário pode então recuperar o dinheiro utilizando a chave pública e a chave privada.
**_O que é uma chave pública?_** Uma chave pública é a chave fornecida as demais pessoas. Em um sistema de chave pública comum, um usuário gera uma chave pública e uma chave privada e, em seguida, dá a chave pública para as pessoas. Esses destinatários podem criptografar informações com a chave pública, mas não podem ser descriptografadas com a mesma chave devido à assimetria do par de chaves.
**_O que é uma chave privada?_** Uma chave privada está vinculada a uma chave pública em um par de chaves. Em um sistema de chave pública comum, um usuário mantém sua chave privada segura e a usa para descriptografar as mensagens que foram criptografadas com sua chave pública antes de serem enviadas a ele.
**_O que é uma assinatura?_** Uma mensagem (ou mais comumente, um hash de uma mensagem) pode ser assinada com uma chave privada, criando uma assinatura. Qualquer pessoa com a chave pública correspondente pode validar a assinatura, o que verifica se o assinante possui a chave privada associada à chave pública em questão. O _SegWit_ é um formato específico para armazenar uma assinatura na rede Bitcoin que falaremos mais especificamente no futuro.
**_O que é uma função hash?_** Uma função hash é um algoritmo frequentemente usado com a criptografia. É uma maneira de mapear uma grande quantidade arbitrária de dados em uma quantidade pequena e fixa de dados. As funções hash usadas na criptografia são unilaterais e resistentes a colisões, o que significa que um hash pode ser vinculado de forma confiável aos dados originais, mas os dados originais não podem ser regenerados a partir do hash. Assim, os hashes permitem a transmissão de pequenas quantidades de dados para representar grandes quantidades de dados, o que pode ser importante para a eficiência e os requisitos de armazenamento.
O Bitcoin aproveita a capacidade do hash de disfarçar os dados originais, o que permite ocultar a chave pública real do usuário, tornando as transações resistentes à computação quântica.
### Criptografia de Chave Pública Em Resumo
Uma maneira de pensar na criptografia de chave pública é: _um jeito de qualquer pessoa proteger os dados de forma que apenas uma pessoa autorizada possa acessá-los e também possa provar que tem esse acesso._
## Sobre CCE
CCE é um acrônimo para criptografia de curva elíptica(em inglês: ECC, ou Elliptic-Curve Cryptography). É um ramo específico da criptografia de chave pública que depende de cálculos matemáticos usando curvas elípticas definidas sobre campos finitos. É mais complexo e difícil de explicar do que a criptografia de chave pública clássica (que usava números primos), mas tem algumas vantagens interessantes.
A CCE não receberá tanta atenção neste tutorial. Isso porque falaremos mais sobre a integração com servidores Bitcoin Core e Lightning, que já cuidaram da parte criptografia para você. Na verdade, a intenção deste tutorial é que você não precise se preocupar com a criptografia, porque isso é algo que você _realmente_ deseja que os especialistas lidem.
**_O que é uma curva elíptica?_** Uma curva elíptica é uma curva geométrica que assume a forma ``y`` <sup>`` 2`` </sup> = ``x`` <sup> ``3`` </sup> `` + ax + b``. Uma curva elíptica específica é escolhida selecionando valores específicos de ``a`` e ``b``. A curva deve ser examinada cuidadosamente para determinar se funciona bem para criptografia. Por exemplo, a curva secp256k1 usada pelo Bitcoin é definida como ``a = 0`` e ``b = 7``.
Qualquer linha que cruze uma curva elíptica o fará em 1 ou 3 pontos... e essa é a base da criptografia de curva elíptica.
**_O que são campos finitos?_** Um campo finito é um conjunto finito de números, onde todas as adições, subtrações, multiplicações e divisões são definidas de forma que resultem em outros números que também estarão no mesmo campo finito. Uma maneira simples de criar um campo finito é por meio do uso da aritmética modular.
**_Como uma curva elíptica é definida sobre um campo finito?_** Uma curva elíptica definida sobre um campo finito tem todos os pontos em sua curva desenhados a partir de um campo finito específico. Ele assume a forma: ``y``<sup>``2``</sup>``% tamanho-do-campo = (x``<sup>``3``</sup>`` + ax + b) % tamanho-do-campo``. O campo finito usado para secp256k1 é ``2``<sup>``256``</sup>``-2``<sup>``32``</sup>``-2``<sup>``9``</sup>``-2``<sup>``8``</sup>``-2``<sup>``7``</sup>``-2``<sup>``6``</sup>``-2``<sup>``4``</sup>``-1``.
**_Como as curvas elípticas são usadas na criptografia?_** Na criptografia de curva elíptica, um usuário seleciona um número muito grande (256 bits) como sua chave privada. Ele então adiciona um ponto base definido na curva a si mesmo tantas vezes. (Na secp256k1, o ponto de base é ``G = 04 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798 483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8`` que prefixa as duas partes da tupla com um ``04`` para dizer que o ponto de dados está na forma descompactada. Se você preferir uma definição geométrica direta, é o ponto "0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0x483ADA7726A3C4655DA4FBFC0E1108A8FD0817B07029BFCDB2DCE28D959F2815B16F81798,0x483ADA7726A3C4655DA4FBFC0E1108A8FD0817B44810A"). O número resultante é uma chave pública. Várias fórmulas matemáticas podem então ser usadas para provar a propriedade da chave pública, dada a chave privada. Como acontece com qualquer função criptográfica, esta é uma armadilha: É fácil passar de uma chave privada para uma chave pública e praticamente impossível de passar de uma chave pública para uma chave privada.
Essa metodologia específica também explica por que os campos finitos são usados em curvas elípticas: Ela garante que a chave privada não ficará muito grande. Observe que o campo finito para secp256k1 é ligeiramente menor que 256 bits, o que significa que todas as chaves públicas terão 256 bits, assim como as chaves privadas.
**_Quais são as vantagens da CCE?_** A principal vantagem da CCE é que ele permite a mesma segurança da criptografia de chave pública clássica com uma chave muito menor. Uma chave pública de curva elíptica de 256 bits corresponde a uma chave pública tradicional (RSA) de 3072 bits.
### CCE Em Resumo
Uma maneira de pensar na CCE é: _um jeito de permitir a criptografia de chave pública usando chaves muito pequenas e uma matemática bem obscura._
## Sobre Blockchains
A blockchain é a generalização da metodologia usada pelo Bitcoin para criar um livro razão distribuído globalmente. O Bitcoin é uma blockchain, assim como qualquer outra moeda alternativa, cada um dos quais vive em sua própria rede e grava em sua própria cadeia de blocos. As sidechains como a _Liquid_ são blockchains também. As blockchains não precisam necessariamente ser relacionadas com finanças. Por exemplo, existem várias discussões para implementar blockchains em soluções para proteger identidades autossoberanas.
Embora precise entender os fundamentos de como uma blockchain funciona para entender como as transações funcionam no Bitcoin, não é necessário muito mais do que isso. Como as blockchains se tornaram uma ampla categoria de tecnologia, esses conceitos básicos provavelmente serão aplicáveis a muitos outros projetos neste setor de tecnologia em crescimento. Porém, os comandos de programação específicos aprendidos neste livro não serão abrangentes a várias utilizações, já que são específicos para Bitcoin (e para a Lightning).
**_Por que é chamado de cadeia de blocos?_** Cada bloco na blockchain armazena um hash do bloco anterior. Isso liga o bloco atual de volta ao "bloco de gênese" original por meio de uma cadeia de blocos ininterrupta. É uma forma de criar uma ordem absoluta entre os dados possivelmente conflitantes. Isso também fornece a segurança da blockchain, porque cada bloco é empilhado sobre um antigo tornando mais difícil recriar o bloco antigo devido aos algoritmos de prova de trabalho utilizados na criação do bloco. Depois que vários blocos foram construídos sobre uma cadeia de blocos, ele é essencialmente irreversível.
**_O que é um fork?_** Ocasionalmente, dois blocos são criados ao mesmo tempo. Isso cria, temporariamente, um fork de um bloco, onde qualquer um dos blocos atuais pode ser o "verdadeiro". De vez em quando, um fork pode se expandir para dois blocos, três blocos ou mesmo quatro blocos de comprimento, mas muito rapidamente um lado da bifurcação é determinado como o verdadeiro e o outro se torna o que chamamos de "órfão". Isso faz parte do processo estocástico de criação de bloco e demonstra por que vários blocos devem ser construídos sobre um bloco antes que ele possa ser considerado verdadeiramente confiável e não rejeitável.
### Blockchain Em Resumo
Uma maneira de pensar na blockchain é: _Uma série vinculada de blocos de dados imutáveis, até o seu bloco inicial._
Outra forma é: _Uma série de blocos vinculados para ordenar dados absolutos que podem ser conflitantes_.
## A Blockchain é Adequada para Mim?
Se você deseja negociar bitcoins, então obviamente a Bitcoin é adequada para você. No entanto, de forma mais ampla, a blockchain se tornou uma cultura pop da atualidade, embora não seja uma solução mágica para todos os problemas técnicos. Dito isso, existem muitas situações específicas em que a blockchain é uma tecnologia superior.
Blockchains provavelmente _serão_ úteis nos seguintes casos:
* Os usuários não confiam uns nos outros.
* Ou: Os usuários estão em diferentes localidades.
* Os usuários não confiam nas autoridades centrais.
* E: Os usuários desejam controlar seus próprios destinos.
* Os usuários desejam uma tecnologia transparente.
* Os usuários desejam compartilhar algo.
* E: Os usuários desejam que o que é compartilhado seja registrado permanentemente.
* Os usuários desejam uma transação final rápida.
* Mas: Os usuários não precisam de uma transação final instantânea.
Blockchains provavelmente _não_ serão úteis caso:
* Os usuários sejam confiáveis:
* Por exemplo: As transações ocorrem dentro de uma empresa ou organização.
* Por exemplo: As transações são supervisionadas por uma autoridade central.
* O sigilo é obrigatório:
* Por exemplo: As informações devem ser secretas.
* Por exemplo: As transações devem ser secretas.
* Por exemplo: As pessoas que estão transacionando devem ser secretas.
* A menos que: uma metodologia para sigilo criptográfico seja cuidadosamente considerada, analisada e testada.
* Os usuários precisam de transações finais instantâneas:
* Por exemplo: Em menos de 10 minutos em uma rede semelhante a Bitcoin, em menos de 2,5 minutos em uma rede semelhante a Litecoin, em menos de 15 segundos em uma rede semelhante a Ethereum.
Observe que ainda pode haver soluções para algumas dessas situações dentro do ecossistema Bitcoin. Por exemplo, os canais de pagamento estão lidando rapidamente com questões de liquidez e finalização do pagamento.
## Sobre a Lightning
A Lightning é um protocolo de segunda camada que interage com o Bitcoin para permitir que os usuários troquem seus bitcoins "offchain" (fora da blockchain). Possui vantagens e desvantagens em relação ao uso da camada principal do Bitcoin.
A Lightning também é um dos focos deste tutorial. Embora o ponto principal seja sobre a interação direta com o Bitcoin (e o `bitcoind`), vamos falar um pouco sobre a Lightning e o porque é uma tecnologia que está prestes a se tornar uma alternativa popular ao Bitcoin, em um futuro próximo. Este livro tem a mesma abordagem para a Lightning e para o Bitcoin: Ele ensina como interagir diretamente com a Lightning de maneira confiável à partir da linha de comando.
Ao contrário do Bitcoin, existem várias variantes da Lightning. Este tutorial usa a implementação compatível do padrão [c-lightning](https://github.com/ElementsProject/lightning) como sendo seu servidor Lightning confiável.
**_O que é um protocolo de segunda camada?_** Um protocolo de segunda camada no Bitcoin funciona tendo como base o Bitcoin. Nesse caso, a Lightning trabalha em cima do Bitcoin, interagindo com ele por meio de contratos inteligentes.
**_O que é um canal Lightning?_** Um canal Lightning é uma conexão entre dois usuários utilizando a Lightning. Cada um dos usuários bloqueia uma quantidade de bitcoins na blockchain do Bitcoin usando uma assinatura multi-sig, criada e assinada por ambos. Os dois usuários podem, então, trocar bitcoins por meio do canal Lightning sem precisar gravar nada na blockchain Bitcoin. Somente quando desejam fechar o canal, eles liquidam os bitcoins, com base na divisão no saldo final das partes.
**_O que é a Lightning Network?_** A junção de todos os canais da Lightning criam a Lightning Network. Isso permite que dois usuários que não tenham um canal entre si troquem bitcoins usando Lightning: O protocolo forma uma cadeia de canais entre os dois usuários e, em seguida, troca as moedas através da cadeia usando transações que chamamos de _time-locked transactions_.
**_Quais são as vantagens da Lightning?_** A Lightning permite transações mais rápidas com taxas mais baixas. Isso cria a possibilidade real de micropagamentos usando bitcoin. Ela também oferece maior privacidade, uma vez que está fora da rede, com apenas o primeiro e o último estado da transação sendo gravados blockchain do Bitcoin.
**_Quais são as desvantagens do Lightning?_** A Lightning ainda é uma tecnologia muito nova e não foi testada tão exaustivamente quanto o Bitcoin. Isso não é apenas uma questão de implementação tecnológica, mas também se o design que pode ser manipulado de maneiras não pensadas anteriormente.
### Resumindo a Lightning
Uma maneira de pensar na Lightning é: _Um jeito de transacionar bitcoins usando canais offchain entre duas pessoas, de modo que apenas o primeiro e o último estado precisem ser gravados na blockchain_.
## Resumo: Apresentando o Bitcoin
O Bitcoin é um sistema _peer-to-peer_ que permite a transferência de fundos por meio de transações bloqueadas por quebra-cabeças. Esses quebra-cabeças dependem da criptografia de curva elíptica de chave pública. Quando você generaliza as ideias por trás do Bitcoin, encontra-se as blockchains, uma tecnologia que atualmente está crescendo e inovando muitos setores. Quando você expande as ideias por trás do Bitcoin, obtém protocolos de segunda camada, como a Lightning, que expandem o potencial da moeda.
## O Que Vem Depois?
Vamos avançar em "Se Prepararando para o Bitcoin" com o [Capítulo Dois: Configurando um Bitcoin-Core VPS](02_0_Setting_Up_a_Bitcoin-Core_VPS.md).

View File

@ -0,0 +1,26 @@
# Capítulo 2: Configurando um Bitcoin-Core VPS
Para começar a usar o Bitcoin, primeiro precisamos configurar uma máquina que execute o Bitcoin. Os artigos neste capítulo descrevem como fazer isso, principalmente usando um VPS (Virtual Private Server).
## Objetivos deste Capítulo
Depois de passar por este capítulo, um desenvolvedor será capaz de:
* Decidir entre os cinco principais tipos de nodes de Bitcoin;
* Criar um node Bitcoin para desenvolvimento;
* Crie uma instância local da Blockchain do Bitcoin.
Os objetivos secundários incluem a capacidade de:
* Compreender a configuração da rede básica do VPS;
* Decidir quais prioridades de segurança implementar;
* Entender a diferença entre os nodes prunados e os não prunados;
* Entender a diferença entre nodes Mainnet, Testnet e Regtest;
* Interpretar os fundamentos do arquivo de configuração do Bitcoin.
## Tabela de Conteúdo
Na verdade, não é preciso ler este capítulo inteiro. Decida se gostaria de executar um StackScript para configurar um node em um VPS Linode (§2.2); Ou você deseja configurar em um ambiente diferente, como em uma máquina AWS ou um Mac (§2.3). Em seguida, vá para a seção mais apropriada. Informações adicionais sobre nossas configurações sugeridas também podem ser encontradas no [Apêndice I](A1_0_Understanding_Bitcoin_Standup.md).
* [Seção Um: Configurando um Bitcoin-Core VPS com Bitcoin Standup](02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md)
* [Seção Dois: Configurando uma Máquina Bitcoin-Core de Outras Maneiras](02_2_Setting_Up_Bitcoin_Core_Other.md)

View File

@ -0,0 +1,253 @@
# 2.1: Configurando um Bitcoin-Core VPS com Bitcoin Standup
Este documento explica como configurar um VPS (Virtual Private Server, ou no português, Servidor Privado Virtual) para rodar um node do Bitcoin usando o Linode.com, instalado usando um StackScript automatizado do [projeto Bitcoin Standup](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts). Apenas precisamos copiar e colar alguns comandos e inicializar o VPS. Quase que imediatamente após a inicialização, encontraremos o nosso novo node do Bitcoin baixando os blocos.
> :warning: **AVISO:** Não podemos usar o VPS para uma carteira de bitcoin com saldos significativos e reais; vamos ler o http://blog.thestateofme.com/2012/03/03/lessons-to-be-learned-from-the-linode-bitcoin-incident/. Ele é muito bom para poder experimentar com transações de bitcoin reais em um node online sem usar um servidor auto-hospedado na nossa rede local. Ele também é útil para poder usar em um iPhone ou iPad para se comunicar via SSH com o nosso VPS para fazer algumas tarefas Bitcoin simples. Mas é necessário um nível mais alto de segurança para utilizarmos saldos grandes e reais.
* Se quisermos saber o que essa configuração faz, podemos ler o [Apêndice I: Compreendendo o Bitcoin Standup](A1_0_Understanding_Bitcoin_Standup.md) enquanto o instalamos;
* Se, ao invés disso, quisermos configurá-lo em outra máquina que não seja um VPS na Linode, como uma máquina na AWS ou um Mac, podemos ir para a seção [§2.2: Configurando um Bitcoin-Core de Outras Maneiras](02_2_Setting_Up_Bitcoin_Core_Other.md)
* Se já temos um node do Bitcoin rodando, podemos ir para o [Capítulo 03: Compreendendo a configuração do node Bitcoin](03_0_Understanding_Your_Bitcoin_Setup.md).
## Começando com o Linode
O Linode é um serviço de hospedagem na nuvem que oferece servidores rápidos e baratos com armazenamento SSD. Nós a utilizamos neste tutorial principalmente porque os StackScripts feitos para BASH oferecem uma maneira fácil de automaticamente configurar um node Bitcoin sem confusão e bagunça.
### Configurando uma Conta no Linode
Podemos criar uma conta na Linode por aqui:
```
https://www.linode.com
```
Se preferirmos, o seguinte código de indicação nos dará dois meses de uso grátis (até U$100), ótimo para aprender sobre o Bitcoin:
[https://www.linode.com/?r=3c7fa15a78407c9a3d4aefb027539db2557b3765](https://www.linode.com/?r=3c7fa15a78407c9a3d4aefb027539db2557b3765)
Precisaremos informar um endereço de email e depois pré-carregar o dinheiro usando um cartão de crédito ou conta do PayPal para eventuais custos futuros.
Quando estiver terminado, devemos cair na seguinte página [https://cloud.linode.com/dashboard](https://cloud.linode.com/dashboard).
### Considerando a Autenticação de Dois Fatores
A segurança do seu servidor não estará completa se pessoas possam invadir a sua conta da Linode, então considere ativar a Autenticação de Dois Fatores para ele. Você pode encontrar essa configuração na [página Minha Conta: Senha e Autenticação](https://manager.linode.com/profile/auth). Se você não fizer isso agora, anote como tarefa para voltar e fazê-lo depois.
## Criando a Imagem Linode usando um StackScript
### Carregando o StackScript
Vamos fazer o download do [Linode Standup Script](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts/blob/master/Scripts/LinodeStandUp.sh) pelo [repositório do Bitcoin Standup Scripts](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts). Este script basicamente automatiza todas as instruções de configuração do VPS Bitcoin. Se quisermos ser mais prudentes, podemos lê-lo com atenção. Se estivermos satisfeito, pode copiar o StackScript para nossa conta do Linode e selecionar [Criar Novo StackScript](https://cloud.linode.com/stackscripts/create). Vamos dar a ele um nome (usamos `Bitcoin Standup`), então vamos copiar e colar o script. Vamos escolher o Debian 10 para nossa imagem alvo e clicar em "Salvar".
### Fazendo a Configuração Inicial
Agora estamos prontos para criar um node baseado no StackScript.
1. Na [página de StackScripts](https://cloud.linode.com/stackscripts?type=account), cliquemos em "..." à esquerda do novo script e vamos escolher o "Deploy New Linode";
2. Coloquemos um Short Hostname e Fully Qualified Hostname;
* **Short Hostname.** Vamos escolher um nome para o VPS. Por exemplo, "meutestebtc";
* **Fully Qualified Hostname.** Se formos incluir este VPS como parte de uma rede com informações de DNS completos, vamos escrever o hostname com nosso domínio. Por exemplo, "meutestebtc.meudominio.com". Caso contrário, vamos apenas repitir o hostname curto e adicione ".local", por exemplo "meutestebtc.local";
3. Coloquemos a senha do usuário "standup";
4. Vamos escolher um Installation Type nas opções avançadas.
* **Installation Type.** Provavelmente será "Mainnet" ou "Pruned Mainnet" se estivermos configurando um node para usar e "Testnet" ou "Pruned Testnet" se estivermos apenas testando. A maior parte deste tutorial irá assumir que tenhamos escolhido o "Pruned Testnet", mas devemos conseguir segui-lo mesmo com os outros tipos. Veja a [Sinopse](#synopsis-bitcoin-installation-types) para maiores informações sobre essas opções. (Percebamos que se estivermos planejando tentar colocar em prática os capítulos da Lightning, provavelmente nos daremos melhor com um node não prunado, pois trabalhar com nodes prunados na Lightning é algo bem experimental. Vamos até a seção [§19.1](19_1_Verifying_Your_Lightning_Setup.md#compiling-the-source-code) para maiores informações);
5. Vamos preencher quaisquer outras opções avançadas aplicáveis;
* **X25519 Public Key.** Esta é a chave pública para adicionar à lista de clientes autorizados do Tor. Se não a utilizarmos, qualquer pessoa que obtiver acesso ao QR code do nosso node podendo assim acessá-lo. Receberemos esta chave pública do cliente que estivermos utilizando para acessar o node. Por exemplo, se estivermos utilizando a [FullyNoded 2](https://github.com/BlockchainCommons/FullyNoded-2), podemos ir às configurações e clicar em "Export Tor V3 Authentication Public Key" para usá-la aqui;
* **SSH Key.** Vamos copiar a chave SSH do computador local para este campo; isto permite que possamos fazer login automaticamente usando a conta standup via SSH. Se ainda não configuramos uma chave SSH no nosso computador local, o [Github](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/) contém boas instruções para fazermos isso. Provavelmente também iremos querer adicionar nossa chave SSH ao nosso LISH (Linode Interactive Shell) através do nosso "Linode Home Page/My Preferences/LISH Settings/LISH Keys". Usar o SSH nos proporcionará uma maneira mais fácil e simples de fazer login no nosso servidor;
* **SSH-Allowed IPs.** Esta é uma lista de endereços IP separados por vírgula que serão autorizados a se conectarem via SSH ao nosso VPS. Por exemplo "192.168.1.15,192.168.1.16". Se não adicionarmos nenhum IP, _o nosso VPS não estará muito seguro_. Ele será bombardeado constantemente por hackers tentando encontrar uma forma de adentrá-lo, e podem conseguir;
4. Selecione uma Imagem;
* **Target Image.** Se seguimos as instruções, as configurações irão nos deixar selecionar apenas o "Debian 10" (apesar de que "Debian 9" tem funcionado com versões posteriores deste StackScript e pode ser que ainda funcione);
5. Escolha uma região para onde o Linode ficará hospedado.
*_Todas as questões remanescentes têm a ver com as mecânicas de implantar o VPS e devem ser deixadas como estão, com uma exceção: aumentar o Swap Disk de 256MB para 512MB, para assegurarmos de que teremos memória suficiente para baixar a blockchain._
Finalmente, deveremos preencher a senha root, que será a senha usada para a conta root.
### Escolhendo Outras Opções do Standup
A Blockchain Commons ainda está no processo de expandir os Bitcoin Standup Scripts com opções para a instalação da Lightning e outras aplicações notáveis do Bitcoin. Podemo dar uma olhada nas opções extras para ver se elas são coisas com as quais gostaríamos de brincar. Em particular, se a Lightning for uma opção, nós sugerimos que instalá-la, porque facilitará bastante os capítulos [19](19_0_Understanding_Your_Lightning_Setup.md) e [20](20_0_Using_Lightning.md).
### Escolhendo um Plano da Linode
Em seguida, escolheremos um plano da Linode.
Um Linode de 4GB será suficiente para a maioria das configurações, incluindo: Mainnet Prunada, Testnet Prunada, e até Testnet não prunada. Todos estes usam menos de 50GB de armazenamento e 4GB é uma quantidade confortável de memória. Este é o plano que recomendamos. Ele consome 20 dólares por mês.
Se, ao invés disso, quisermos ter um node Mainnet não prunada em um VPS, precisaremos instalar um Linode em um disco com mais de 280GB(!), que no momento é o Linode 16GB, que tem 320GB de armazenamento e 16GB de memória, custando aproximadamente 80 dólares por mês. Nós _não_ recomendamos este plano.
A tabela à seguir mostra os requisitos mínimos:
| Configuração | Memória | Armazenamento | Linode |
|-------|--------|---------|---------|
| Mainnet | 2G | 280G | Linode 16GB |
| Mainnet Prunada | 2G | ~5G | Linode 4GB |
| Testnet | 2G | ~15G | Linode 4GB |
| Testnet Prunada | 2G | ~5G | Linode 4GB |
| Regtest | 2G | ~ | Linode 4GB |
Mas podem existir maneiras de reduzir os custos.
* Para as máquinas que sugerimos o **Linode 4GB**, podemos conseguir reduzí-las para um Linode 2GB. Algumas versões do Bitcoin Core têm funcionado bem com esta quantidade, outras têm esgotado a memória de vez em quando e depois recuperado, e outras têm esgotado a memória continuamente. Lembre-se de aumentar o Swap Disk para maximizar as chances de funcionar. Use por sua conta e risco;
* Para a Mainnet Não Prunada, surgerimos um **Linode 16GB**, porém provavelmente conseguiremos utilizar um Linode 4GB, mas precisaremos adicionar um [Block Storage](https://cloud.linode.com/volumes) suficiente para armazenar a blockchain. Esta é com certeza uma solução melhor para o longo prazo porque os requisitos de armazenamento da blockchain do Bitcoin aumentam continuamente se não a prunarmos, enquanto os requisitos de CPU não aumentam (ou pelo menos não nas mesmas proporções). Um armazenamento GibiByte de 320GB custaria U$32 por mês, que combinado com um Linode 4GB custa U$52 por mês, ao invés de U$80, e mais importante, podemos continuar aumentando-o. Nós não documentamos esta configuração por completo por duas razões: (1) nós não sugerimos a configuração mainnet não prunada, então suspeitamos ser uma configuração incomum; e (2) nós não testamos como volumes Linode comparam com nossos SSDs intrínsecos em performance e uso. Mas existe uma documentação completa na página do Block Storage. Precisaríamos configurar o Linode, executar o stackscript, e então interrompê-lo para mover o armazenamento da blockchain para um volume comissionado antes de continuarmos.
### Fazendo a Configuração Final
A última coisa que precisamos fazer é colocar a senha root. (Se tivermos nos esquecido de algo, seremos informados agora).
Clique em "Deploy" para inicializar os discos e preparar o VPS. Tudo deve ser executado em menos de um minuto. Quando estiver pronto veremos, na "Host Job Queue", botões verdes de "Success" dizendo "Disk Create from StackScript - Setting password for root... done." e "Create Filesystem - 256MB Swap Image".
Agora podemos querer alterar o nome do nosso VPS Linode do padrão `linodexxxxxxxx`. Vamos na aba de configurações e vamos alterar o rótulo para algo mais útil, como o hostname curto do nosso VPS. Por exemplo, podemos chamá-lo de `bitcoin-testnet-prunada` para diferenciá-lo de outros VPSs em nossa conta.
## Fazendo Login no Nosso VPS
Se olharmos o painel de controle do nosso Linode, devemos ver o novo computador se iniciar. Quando o serviço atingir 100%, poderemos fazer o login.
Primeiramente, precisaremos do endereço de IP. Clique na aba "Linodes" e uma lista dos nossos VPSs deve aparecer, além do fato de que ele está online, o seu "plano", endereço de IP, e outras informações.
Vamos para o console local e vamos fazer login na conta `standup` usando aquele endereço:
```
ssh standup@[IP-ADDRESS]
```
Por exemplo:
```
ssh standup@192.168.33.11
```
Se configuramos o nosso VPS para usar uma chave SSH, o login deve ser automático (possivelmente requisitando a senha SSH para desbloquear a chave). Se não tivermos configurado a chave SSH, então precisaremos escrever a senha do user1.
### Esperando Alguns Instantes
Aqui vai uma pequena sacada: _o nosso StackScript está executando agora_. O script BASH é executado na primeira vez que o VPS é ligado. O que significa que o nosso VPS ainda não está pronto.
O tempo total de execução é por volta de 10 minutos. Então, vamos usar este intervalo para fazer um café, ou apenas relaxar por alguns instantes. Há duas partes do script que demoram um pouco: a atualização de todos os pacotes do Debian e o download do código do Bitcoin. Eles devem demorar não mais que 5 minutos cada, o que significa que se voltarmos em uns 10 minutos, provavelmente tudo estará pronto.
Se estivermos impaciente, podemos pular e usar o `sudo tail -f /standup.log`, que mostrará o progresso da instalação, como descrito na próxima seção.
## Verificando Nossa Instalação
Saberemos que o stackscript terminou quando a `tail` do `standup.log` disser algo como o seguinte:
```
/root/StackScript - Bitcoin is setup as a service and will automatically start if your VPS reboots and so is Tor
/root/StackScript - You can manually stop Bitcoin with: sudo systemctl stop bitcoind.service
/root/StackScript - You can manually start Bitcoin with: sudo systemctl start bitcoind.service
```
Nesse momento, nosso diretório home se parecerá com isso:
```
$ ls
bitcoin-0.20.0-x86_64-linux-gnu.tar.gz laanwj-releases.asc SHA256SUMS.asc
```
Esses são os vários arquivos que foram usados para instalar o Bitcoin no nosso VPS. _Nenhum_ deles é necessário. Nós apenas os deixamos lá caso queiramos fazer qualquer verificacão adicional. Caso contrário, podemos deletá-los:
```
$ rm *
```
### Verificando a Configuração do Bitcoin
Para ter certeza de que o Bitcoin baixado é válido, o StackScript checa a assinatura e o checksum SHA. Devemos verificar se ambos os testes foram bem sucedidos:
```
$ sudo grep VERIFICATION /standup.log
```
Se observarmos algo como o descrito abaixo, tudo estará OK:
```
/root/StackScript - VERIFICATION SUCCESS / SIG: gpg: Good signature from "Wladimir J. van der Laan (Bitcoin Core binary release signing key) <laanwj@gmail.com>" [unknown]
/root/StackScript - VERIFICATION SUCCESS / SHA: 35ec10f87b6bc1e44fd9cd1157e5dfa4```
```
Entretanto, se qualquer uma dessas verificações retornar "VERIFICATION ERROR", então temos um problema. Como tudo isso é programado, é possível que tenha ocorrido apenas uma mudança pequena que causou erros nas verificações do script. Isto aconteceu poucas vezes durante a existência do script que virou o Standup. Mas, também é possível que alguém esteja tentando te empurrar uma cópia falsa do daemon do Bitcoin. Então, _precisamos ter a certeza absoluta que sabemos o que de fato aconteceu antes de usarmos o Bitcoin!_
### Lendo os Logs
Também podemos querer ler todos os logs dos arquivos de configuração para se assegurar de que nada imprevisível aconteceu durante a instalação.
É melhor olhar o arquivo de log padrão do StackScript, que tem todas as saídas, incluindo os erros:
`$ sudo more /standup.log`
Podemos observar que é totalmente normal ver _alguns_ erros, particularmente quando executamos o software gpg e quando várias coisas tentam acessar o dispositivo `/dev/tty` inexistente.
Se, ao invés disso, quisermos olhar para um conjunto menor de informação, todos os erros devem estar em:
`$ sudo more /standup.err`
Ele ainda contém uma certa quantidade de informação além de erros, mas é uma leitura mais rápida.
Se tudo estiver OK, parabéns, temos um node Bitcoin funcionando usando o Linode!
## O Que Nós Fizemos
Apesar de a imagem padrão do Debian 10 que estamos usando para o VPS ter sido modificada pelo Linode para ser razoavelmente seguro, o nosso node Bitcoin instalado pelo StackScript Linode é configurado com um nível de segurança ainda maior. Isto pode ser limitante, ou pode nos impedir de fazer algumas coisas que esperávamos conseguir fazer. O que segue são algumas dicas à respeito disso:
### Serviços Protegidos
A instalação do Bitcoin VPS é mínima e permite pouco tipo de comunicação. Isto é feito através do "uncomplicated firewall" (`ufw`), que bloqueia tudo, exceto conexões SSH. Também existe alguma segurança adicional possível para as portas RFC, graças aos serviços ocultos instalados pelo Tor.
**Ajustando o UFW.** Provavelmente deveremos deixar o UFW no estágio de super-protegido! Não devemos usar uma máquina Bitcoin para outros serviços, porque cada um aumenta a vulnerabilidade! Se decidirmos o oposto, existem vários [guias para o UFW](https://www.digitalocean.com/community/tutorials/ufw-essentials-common-firewall-rules-and-commands) que podem nos ajudar a adicionar outros serviços. Como o nome diz, é _uncomplicated_. Por exemplo, adicionar serviços de email requeriria apenas abrir a porta de mail: `sudo ufw allow 25`. Mas não vamos fazer isso, não é mesmo.
**Ajustando o Tor.** Podemos querer proteger os serviços como SSH de uma maneira melhor. Podemos ler sobre isso no [Capítulo 12: Usando o Tor](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/12_0_Using_Tor.md), para maiores informações sobre o Tor.
### Shells Protegidos
Se definimos o "SSH-allowed IPs", o acesso SSH (e SCP) ao servidor é bastante restrito. `/etc/hosts.deny` impede qualquer um de se logar. _Nós não recomendamos que isso seja alterado_. `/etc/hosts.allow` então autoriza endereços de IP específicos. Podemos apenas adicionar mais endereços de IP em uma lista separada por vírgulas se precisarmos oferecer mais acesso.
Por exemplo:
```
sshd: 127.0.0.1, 192.128.23.1
```
### Atualizações Automáticas
O Debian também é configurado para se atualizar automaticamente para garantir de que mantenha atualizado aos patches de segurança mais recentes.
Se, por alguma razão, desejarmos alterar isso (_algo que não recomendamos_), podemos fazer o seguinte:
```
echo "unattended-upgrades unattended-upgrades/enable_auto_updates boolean false" | debconf-set-selections
```
_Se quisermos saber mais sobre o que o Bitcoin Standup StackScript faz, podemos ler o [Apêndice I: Compreendendo o Bitcoin Standup](A1_0_Understanding_Bitcoin_Standup.md)_.
## Brincando com o Bitcoin
Agora, provavelmente desejaremos brincar com o Bitcoin!
Mas calma, provavelmente o nosso daemon do Bitcoin ainda está baixando os blocos. O `bitcoin-cli getblockcount` irá dizer como está indo:
```
$ bitcoin-cli getblockcount
1771352
```
Se o resultado for diferente a cada vez que digitarmos o comando, precisaremos esperar antes de começar a trabalhar com o Bitcoin. Isto levará, atualmente, de 1 a 6 horas para um node prunado, dependendo das especificações da nossa máquina.
Mas quando estabilizar em um número, estaremos prontos para continuar!
Mesmo assim, pode ser uma boa hora para mais alguns cafézinhos. Mas logo logo o nosso sistema estará pronto, e nós também!
## Resumo: Configurando um Bitcoin-Core VPS Manualmente
Criar um Bitcoin Core VPS com os scripts Standup fizeram com que todo o processo fique rápido, simples, e (esperamos), indolor.
## O Que Vem Depois?
Temos algumas opções para o que podemos seguir:
* Ler o [StackScript](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts/blob/master/Scripts/LinodeStandUp.sh) para entender a configuração;
* Ler o que o StackScript faz no [Apêndice I: Compreendendo o Bitcoin Standup](A1_0_Understanding_Bitcoin_Standup.md);
* Escolher uma metodologia inteiramente alternativa, como descrito na seção [§2.2: Configurando uma Máquina Bitcoin-Core de Outras Maneiras](02_2_Setting_Up_Bitcoin_Core_Other.md);
* Usar o "bitcoin-cli" com o [Capítulo Três: Compreendendo Nossa Configuração do Bitcoin](03_0_Understanding_Your_Bitcoin_Setup.md).
## Sinopse: Tipos de Instalação do Bitcoin
**Mainnet.** Isto irá fazer o download da blockchain inteira do Bitcoin. São 280GB de dados (e está aumentando a cada dia).
**Mainnet Prunada.** Isto irá reduzir a blockchain que iremos armazenar para apenas os últimos 550 blocos. Se não estivermos minerando ou executando outro serviço do Bitcoin, isso deve ser o suficiente para validação.
**Testnet.** Isto nos dará acesso a uma blockchain alternativa do Bitcoin onde os bitcoins não têm valor algum. É feita para experimentos e testes.
**Testnet Prunada.** Isto são apenas os últimos 550 blocos da Testnet ... porque a blockchain da Testnet está meio grande agora também.
**Regtest Privada.** Este é o modo Regression Testing, que nos permite rodar um servidor de Bitcoin totalmente local. Nos permite também realizar testes mais detalhados. Não há um modo prunado aqui, porque estaremos começando a blockchain do zero. Esta é uma configuração bem diferente, então é discutida no [Apêndice 3](A3_0_Using_Bitcoin_Regtest.md).

View File

@ -0,0 +1,18 @@
# 2.2: Configurando uma Máquina Bitcoin-Core de Outras Maneiras
A seção anterior, [§2.1: Configurando um Bitcoin-Core VPS com Bitcoin Standup](02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md), assumimos que iríamos criar um full node em um VPS usando um StackScript Linode. Entretanto, podemos querer criar uma instância do Bitcoin Core via qualquer outra metodologia a nossa escolha e ainda assim acompanhar as próximas etapas deste tutorial.
A seguir estão outras metodologias de configuração das quais temos conhecimento:
* *[Compilar da Fonte](A2_0_Compiling_Bitcoin_from_Source.md).* Se preferirmos compilar o Bitcoin Core manualmente, a maneira como fazer isso é discutida no Apêndice 2.
* *[Usando GordianNode-macOS](https://github.com/BlockchainCommons/GordianNode-macOS).* Se possuirmos um Mac moderno, podemos usar o aplicativo *GordianNode* da Blockchain Commons, que é capacitado pelo *BitcoinStandup*, para instalar um full node nosso Mac.
* *[Usando Outros Scripts de Bitcoin Standup](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts).* A Blockchain Commons também oferece uma versão do script Linode que usamos que pode ser executada pela linha de comando em qualquer máquina Debian ou Ubuntu. Esse tende a ser o script "topo-de-linha", o que significa que terá, mais provavelmente, novas funcionalidades e funções, como a instalação da Lightning.
* *[Configurando um Node Bitcoin na AWS](https://wolfmcnally.com/115/developer-notes-setting-up-a-bitcoin-node-on-aws/).* @wolfmcnally escreveu um tutorial passo-a-passo para a configuração de um Bitcoin Core em um Amazon Web Services (AWS).
* *[Configurando um Node Bitcoin em uma Raspberry Pi 3](https://medium.com/@meeDamian/bitcoin-full-node-on-rbp3-revised-88bb7c8ef1d1).* Damian Mee explica como configurar um full node headless em um Raspberry Pi 3.
## O Que Vem Depois?
A não ser que queiramos retornar a alguma das outras metodologias de criação de um node Bitcoin Core, devemos:
* Seguir em frente para o "bitcoin-cli" com o [Capítulo Três: Compreendendo Nossa Configuração do Bitcoin](03_0_Understanding_Your_Bitcoin_Setup.md).

View File

@ -0,0 +1,31 @@
# Capítulo 3: Compreendendo Nossa Configuração do Bitcoin
Agora que estamos prontos para começar a trabalhar com a interface de linha de comando `bitcoin-cli`. Mas isso requer primeiro que entendamos a configuração do Bitcoin e os recursos da carteira, que é o que será explicado neste capítulo.
Neste e nos próximos capítulos, presumimos que uma VPS com Bitcoin instalado esteja sendo utilizada, e que iremos executar o `bitcoind`. Também presumimos que estamos conectados à testnet, permitindo o acesso a bitcoins sem usar fundos reais. Podemos fazer isso com Bitcoin Standup em linode.com, como vimos na sessão [2.1: Configurando um Bitcoin-Core VPS com Bitcoin Standup](02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md), ou usando os demais métodos, descritos na sessão [2.2: Configurando uma Máquina Bitcoin Core de Outras Maneiras](02_2_Setting_Up_Bitcoin_Core_Other.md).
## Objetivos deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Demonstrar que o node Bitcoin está instalado e atualizado;
* Criar um endereço para receber bitcoins;
* Usar os comandos básicos da carteira;
* Criar um endereço a partir de um descritor.
Os objetivos secundários incluem a capacidade de:
* Compreender o layout básico do arquivo Bitcoin;
* Usar comandos informativos básicos;
* Entender o que é um endereço Bitcoin;
* Entender o que é uma carteira;
* Entender como importar endereços.
## Tabela de Conteúdo
* [Seção Um: Verificando Nossa Configuração do Bitcoin](03_1_Verifying_Your_Bitcoin_Setup.md)
* [Seção Dois: Conhecendo Nossa Configuração do Bitcoin](03_2_Knowing_Your_Bitcoin_Setup.md)
* [Seção Três: Configurando Nossa Carteira](03_3_Setting_Up_Your_Wallet.md)
* [Usando Variáveis de Linha de Comando](03_3__Interlude_Using_Command-Line_Variables.md)
* [Seção Quatro: Recebendo uma Transação](03_4_Receiving_a_Transaction.md)
* [Seção Cinco: Compreendendo o Descritor](03_5_Understanding_the_Descriptor.md)

View File

@ -0,0 +1,103 @@
# 3.1: Verificando Nossa Configuração do Bitcoin
Antes de começarmos a brincar com Bitcoin, devemos nos certificar de que tudo está configurado corretamente.
## Crie os Aliases
Sugerimos a criação de alguns aliases (um tipo de atalho) para facilitar o uso do Bitcoin.
Podemos fazer isso colocando-os em nosso `.bash_profile`, `.bashrc` ou no `.profile`.
```
cat >> ~/.bash_profile <<EOF
alias btcdir="cd ~/.bitcoin/" #linux default bitcoind path
alias bc="bitcoin-cli"
alias bd="bitcoind"
alias btcinfo='bitcoin-cli getwalletinfo | egrep "\"balance\""; bitcoin-cli getnetworkinfo | egrep "\"version\"|connections"; bitcoin-cli getmininginfo | egrep "\"blocks\"|errors"'
EOF
```
Depois de inserir os aliases, podemos usar o comando `source .bash_profile` para inseri-los ou apenas efetuar logout/login novamente.
Observe que os aliases incluem atalhos para executar o `bitcoin-cli`, o `bitcoind` e para ir ao diretório Bitcoin. Esses aliases têm como objetivo principal tornar a nossa vida mais fácil, por isso que damos a sugestão de criar outros apelidos para facilitar o uso de comandos frequentes (e argumentos) e também para minimizar erros. Os aliases desse tipo podem ser ainda mais úteis se tivermos uma configuração complexa onde regularmente executamos comandos associados a Mainnet, com Testnet, _e_ com Regtest, conforme explicaremos mais à frente.
Dito isso, o uso desses aliases _neste_ documento pode acidentalmente deixar algumas das lições principais onde ensinamos sobre o Bitcoin no escuro, então o único alias que usaremos diretamente aqui é `btcinfo` porque ele encapsula um comando muito mais longo e complexo. Caso contrário, iremos mostrar os comandos completos, por isso, podemos ajustar os aliases para nosso próprio uso conforme apropriado.
## Executando o Bitcoind
Começaremos nossa exploração da rede Bitcoin com o comando `bitcoin-cli`. No entanto, o `bitcoind` _deve_ estar em execução para conseguirmos usar o bitcoin-cli, pois ele envia comandos JSON-RPC para o bitcoind. Se estivermos usando a configuração padrão, o bitcoind já deve estar instalado e funcionando. Podemos verificar olhando a tabela de processos.
```
$ ps auxww | grep bitcoind
standup 455 1.3 34.4 3387536 1392904 ? SLsl Jun16 59:30 /usr/local/bin/bitcoind -conf=/home/standup/.bitcoin/bitcoin.conf
```
Se ele não estiver listado, podemos executar o `/usr/local/bin/bitcoind -daemon` manualmente e também colocá-lo em crontab.
## Verificando os Blocos
Vamos partir do pressuposto que já tenhamos baixado todo o blockchain antes de começarmos a brincar. Basta executar o comando `bitcoin-cli getblockcount` para ver tudo está carregado corretamente.
```
$ bitcoin-cli getblockcount
1772384
```
Isso indica que está carregado. Precisamos verificar isso em um serviço online que informa a altura atual do bloco.
> :book: ***O que é a altura do bloco?*** A altura do bloco é a distância que um bloco particular está do bloco de gênese. A altura do bloco atual é a altura do bloco mais recente adicionado a blockchain.
Podemos fazer isso olhando um explorador, como o [Mempool Space Explorer](https://mempool.space/pt/testnet). É o número mais recente corresponde ao `getblockcount`? Se sim, nossa blockchain está atualizada.
Se quisermos que um alias veja tudo de uma vez, o código abaixo funciona normalmente no Testnet, mas pode desaparecer em algum momento no futuro:
```
$ cat >> ~/.bash_profile << EOF
alias btcblock="echo \\\`bitcoin-cli getblockcount 2>&1\\\`/\\\`wget -O - https://blockstream.info/testnet/api/blocks/tip/height 2> /dev/null | cut -d : -f2 | rev | cut -c 1- | rev\\\`"
EOF
$ source .bash_profile
$ btcblock
1804372/1804372
```
> :link: **TESTNET vs MAINNET:** Lembre-se de que este tutorial geralmente assume que estamos usando a Testnet. Se estivermos usando a mainnet, podemos recuperar a altura do bloco atual usando a seguinte linha de comando: `wget -O - https://mempool.space/testnet/api/blocks/tip/height 2> /dev/ null`. Podemos substituir a última metade do alias `btblock` (após `/`) por isso.
Se a nossa blockchain não estiver atualizada, mas nosso `getblockcount` estiver aumentando, não há problema. O tempo total de download pode levar de uma a várias horas, dependendo da configuração.
## Opcional: Conhecendo os Tipos de Servidores
> **TESTNET vs MAINNET:** Ao configurar o node Bitcoin, precisamos escolher se vamos criá-lo como sendo um Mainnet, Testnet ou Regtest. Embora este documento presuma uma configuração de Testnet, vale a pena entender como podemos acessar e usar os outros tipos de configuração, inclusive, como ter todos na mesma máquina! Mas, se formos iniciantes, podemos pular isso, pois não é necessário para uma configuração básica.
O tipo de configuração é controlado principalmente por meio do arquivo `~/.bitcoin/bitcoin.conf`. Se estivermos executando o Testnet, provavelmente teremos a seguinte linha:
```
testnet=1
```
Se estivermos executando a Regtest, provavelmente teremos essa linha:
```
regtest=1
```
No entanto, se desejarmos executar vários tipos diferentes de nós simultaneamente, devemos deixar o um sinalizador Testnet (ou Regtest) fora do nosso arquivo de configuração. Podemos então escolher se estamos usando a Mainnet, Testnet ou Regtest toda vez que executarmos o bitcoind ou o bitcoin-cli.
Aqui está um conjunto de aliases que tornariam isso mais fácil, criando um alias específico para iniciar e parar o bitcoind, para ir para o diretório bitcoin e para executar o bitcoin-cli, na Mainnet (que não tem sinalizadores extras), no Testnet (que é -testnet), ou no nosso Regtest (que é -regtest).
```
cat >> ~/.bash_profile <<EOF
alias bcstart="bitcoind -daemon"
alias btstart="bitcoind -testnet -daemon"
alias brstart="bitcoind -regtest -daemon"
alias bcstop="bitcoin-cli stop"
alias btstop="bitcoin-cli -testnet stop"
alias brstop="bitcoin-cli -regtest stop"
alias bcdir="cd ~/.bitcoin/" #linux default bitcoin path
alias btdir="cd ~/.bitcoin/testnet" #linux default bitcoin testnet path
alias brdir="cd ~/.bitcoin/regtest" #linux default bitcoin regtest path
alias bc="bitcoin-cli"
alias bt="bitcoin-cli -testnet"
alias br="bitcoin-cli -regtest"
EOF
```
Para ainda mais complexidade, podemos fazer com que cada um dos aliases 'start' use o sinalizador -conf para carregar a configuração de um arquivo diferente. Isso vai muito além do escopo deste tutorial, mas o oferecemos como um ponto de partida para quando nossas explorações de Bitcoin atingirem o próximo nível.
## Resumo: Verificando Nossa Configuração do Bitcoin
Antes de começar a brincar com o Bitcoin, devemos nos certificar de que nossos aliases estão configurados, nosso bitcoind está rodando e os blocos foram baixados. Também podemos querer configurar algum acesso a configurações alternativas de Bitcoin, se formos usuários mais avançados.
## O Que Vem Depois?
Continue "Compreendendo Nossa Configuração do Bitcoin" com [3.2: Conhecendo Nossa Configuração do Bitcoin](03_2_Knowing_Your_Bitcoin_Setup.md).

View File

@ -0,0 +1,315 @@
# 3.2: Conhecendo Nossa Configuração do Bitcoin
Antes de começarmos a brincar com Bitcoin, é sempre bom entender melhor nossa configuração.
## Conhecendo o Diretório do Bitcoin
Para começar, devemos entender onde tudo está guardado: O diretório `~/.bitcoin`.
O diretório principal contém apenas nosso arquivo de configuração e o diretório Testnet:
```
$ ls ~/.bitcoin
bitcoin.conf testnet3
```
Os guias de configuração no [Capítulo dois: Criando um VPS Bitcoin-Core](02_0_Setting_Up_a_Bitcoin-Core_VPS.md) estabelecem um arquivo de configuração padronizado. Na sessão [3.1: Verificando a configuração do node Bitcoin](03_1_Verifying_Your_Bitcoin_Setup.md) sugerimos como alterá-la para oferecer suporte a configurações mais avançadas. Se estivermos interessados em aprender ainda mais sobre o arquivo de configuração, podemos consultar o [Gerador de Configuração do Bitcoin Core escrito por Jameson Lopp's](https://jlopp.github.io/bitcoin-core-config-generator/).
Voltando para o diretório `~/.bitcoin`, iremos descobrir que o diretório testnet3 contém todos os elementos:
```
$ ls ~/.bitcoin/testnet3
banlist.dat blocks debug.log mempool.dat peers.dat
bitcoind.pid chainstate fee_estimates.dat onion_private_key wallets
```
Não deve mexer com a maioria desses arquivos e diretórios, particularmente os diretórios `blocks` e `chainstate` não devem ser tocados, pois contêm todos os dados da blockchain, e as informações do nosso diretório `wallets`, que contém nossa carteira. No entanto, podemos prestar atenção ao arquivo `debug.log`, que devemos consultar se começarmos a ter problemas com nossa configuração.
> :link: **TESTNET vs MAINNET:** Se estivermos usando a Mainnet, então _tudo_ será colocado no diretório principal `~/.bitcoin`. Então se estivermos usando a Mainnet, Testnet e a Regtest, veremos que o `~/.bitcoin` contém nosso arquivo de configuração e nossos dados da mainnet, o diretório `~/.bitcoin/testnet3` contém nossos dados da Testnet, e o diretório `~/.bitcoin/regtest` contém os dados do regtest.
## Conhecendo os Comandos do Bitcoin-CLI
A maior parte do nosso trabalho inicial será feito com o comando `bitcoin-cli`, que oferece uma interface simples para o `bitcoind`. Se quisermos mais informações sobre como utilizá-lo, basta executá-lo com o argumento `help`. Sem nenhum outro argumento, ele mostrara todos os possíveis comandos:
```
$ bitcoin-cli help
== Blockchain ==
getbestblockhash
getblock "blockhash" ( verbosity )
getblockchaininfo
getblockcount
getblockfilter "blockhash" ( "filtertype" )
getblockhash height
getblockheader "blockhash" ( verbose )
getblockstats hash_or_height ( stats )
getchaintips
getchaintxstats ( nblocks "blockhash" )
getdifficulty
getmempoolancestors "txid" ( verbose )
getmempooldescendants "txid" ( verbose )
getmempoolentry "txid"
getmempoolinfo
getrawmempool ( verbose )
gettxout "txid" n ( include_mempool )
gettxoutproof ["txid",...] ( "blockhash" )
gettxoutsetinfo
preciousblock "blockhash"
pruneblockchain height
savemempool
scantxoutset "action" ( [scanobjects,...] )
verifychain ( checklevel nblocks )
verifytxoutproof "proof"
== Control ==
getmemoryinfo ( "mode" )
getrpcinfo
help ( "command" )
logging ( ["include_category",...] ["exclude_category",...] )
stop
uptime
== Generating ==
generatetoaddress nblocks "address" ( maxtries )
generatetodescriptor num_blocks "descriptor" ( maxtries )
== Mining ==
getblocktemplate ( "template_request" )
getmininginfo
getnetworkhashps ( nblocks height )
prioritisetransaction "txid" ( dummy ) fee_delta
submitblock "hexdata" ( "dummy" )
submitheader "hexdata"
== Network ==
addnode "node" "command"
clearbanned
disconnectnode ( "address" nodeid )
getaddednodeinfo ( "node" )
getconnectioncount
getnettotals
getnetworkinfo
getnodeaddresses ( count )
getpeerinfo
listbanned
ping
setban "subnet" "command" ( bantime absolute )
setnetworkactive state
== Rawtransactions ==
analyzepsbt "psbt"
combinepsbt ["psbt",...]
combinerawtransaction ["hexstring",...]
converttopsbt "hexstring" ( permitsigdata iswitness )
createpsbt [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount},{"data":"hex"},...] ( locktime replaceable )
createrawtransaction [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount},{"data":"hex"},...] ( locktime replaceable )
decodepsbt "psbt"
decoderawtransaction "hexstring" ( iswitness )
decodescript "hexstring"
finalizepsbt "psbt" ( extract )
fundrawtransaction "hexstring" ( options iswitness )
getrawtransaction "txid" ( verbose "blockhash" )
joinpsbts ["psbt",...]
sendrawtransaction "hexstring" ( maxfeerate )
signrawtransactionwithkey "hexstring" ["privatekey",...] ( [{"txid":"hex","vout":n,"scriptPubKey":"hex","redeemScript":"hex","witnessScript":"hex","amount":amount},...] "sighashtype" )
testmempoolaccept ["rawtx",...] ( maxfeerate )
utxoupdatepsbt "psbt" ( ["",{"desc":"str","range":n or [n,n]},...] )
== Util ==
createmultisig nrequired ["key",...] ( "address_type" )
deriveaddresses "descriptor" ( range )
estimatesmartfee conf_target ( "estimate_mode" )
getdescriptorinfo "descriptor"
signmessagewithprivkey "privkey" "message"
validateaddress "address"
verifymessage "address" "signature" "message"
== Wallet ==
abandontransaction "txid"
abortrescan
addmultisigaddress nrequired ["key",...] ( "label" "address_type" )
backupwallet "destination"
bumpfee "txid" ( options )
createwallet "wallet_name" ( disable_private_keys blank "passphrase" avoid_reuse )
dumpprivkey "address"
dumpwallet "filename"
encryptwallet "passphrase"
getaddressesbylabel "label"
getaddressinfo "address"
getbalance ( "dummy" minconf include_watchonly avoid_reuse )
getbalances
getnewaddress ( "label" "address_type" )
getrawchangeaddress ( "address_type" )
getreceivedbyaddress "address" ( minconf )
getreceivedbylabel "label" ( minconf )
gettransaction "txid" ( include_watchonly verbose )
getunconfirmedbalance
getwalletinfo
importaddress "address" ( "label" rescan p2sh )
importmulti "requests" ( "options" )
importprivkey "privkey" ( "label" rescan )
importprunedfunds "rawtransaction" "txoutproof"
importpubkey "pubkey" ( "label" rescan )
importwallet "filename"
keypoolrefill ( newsize )
listaddressgroupings
listlabels ( "purpose" )
listlockunspent
listreceivedbyaddress ( minconf include_empty include_watchonly "address_filter" )
listreceivedbylabel ( minconf include_empty include_watchonly )
listsinceblock ( "blockhash" target_confirmations include_watchonly include_removed )
listtransactions ( "label" count skip include_watchonly )
listunspent ( minconf maxconf ["address",...] include_unsafe query_options )
listwalletdir
listwallets
loadwallet "filename"
lockunspent unlock ( [{"txid":"hex","vout":n},...] )
removeprunedfunds "txid"
rescanblockchain ( start_height stop_height )
sendmany "" {"address":amount} ( minconf "comment" ["address",...] replaceable conf_target "estimate_mode" )
sendtoaddress "address" amount ( "comment" "comment_to" subtractfeefromamount replaceable conf_target "estimate_mode" avoid_reuse )
sethdseed ( newkeypool "seed" )
setlabel "address" "label"
settxfee amount
setwalletflag "flag" ( value )
signmessage "address" "message"
signrawtransactionwithwallet "hexstring" ( [{"txid":"hex","vout":n,"scriptPubKey":"hex","redeemScript":"hex","witnessScript":"hex","amount":amount},...] "sighashtype" )
unloadwallet ( "wallet_name" )
walletcreatefundedpsbt [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount},{"data":"hex"},...] ( locktime options bip32derivs )
walletlock
walletpassphrase "passphrase" timeout
walletpassphrasechange "oldpassphrase" "newpassphrase"
walletprocesspsbt "psbt" ( sign "sighashtype" bip32derivs )
== Zmq ==
getzmqnotifications
```
Podemos digitar também `bitcoin-cli help [command]` para obtermos informações ainda mais detalhadas sobre aquele comando. Por exemplo:
```
$ bitcoin-cli help getmininginfo
...
Returns a json object containing mining-related information.
Result:
{ (json object)
"blocks" : n, (numeric) The current block
"currentblockweight" : n, (numeric, optional) The block weight of the last assembled block (only present if a block was ever assembled)
"currentblocktx" : n, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled)
"difficulty" : n, (numeric) The current difficulty
"networkhashps" : n, (numeric) The network hashes per second
"pooledtx" : n, (numeric) The size of the mempool
"chain" : "str", (string) current network name (main, test, regtest)
"warnings" : "str" (string) any network and blockchain warnings
}
Examples:
> bitcoin-cli getmininginfo
> curl --user myusername --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getmininginfo", "params": []}' -H 'content-type: text/plain;' http://127.0.0.1:8332/
```
> :book: ***O que é o RPC?*** O`bitcoin-cli` é apenas uma interface útil que permite enviar comandos para o`bitcoind`. Mais especificamente, é uma interface que permite enviar comandos RPC (Remote Procedure Protocol ou, protocolo de procedimento remoto, no português) para o `bitcoind`. Frequentemente, o comando `bitcoin-cli` e o comando RPC possuem nomes e interfaces idênticos, mas alguns comandos no `bitcoin-cli` fornecem atalhos para solicitações RPC mais complexas. Geralmente, a interface `bitcoin-cli` é muito mais limpa e simples do que tentar enviar comandos RPC manualmente, usando `curl` ou algum outro método. No entanto, ele também tem limitações quanto ao que podemos fazer.
## Opcional: Conhecendo as Informações do Node Bitcoin
Uma variedade de comandos bitcoin-cli podem fornecer informações adicionais sobre nossos node Bitcoin. Os mais comuns são:
`bitcoin-cli -getinfo` retorna informações do RPCs mais fáceis de serem lidas.
```diff
$ bitcoin-cli -getinfo
! Chain: test
Blocks: 1977694
Headers: 1977694
Verification progress: 0.9999993275374796
Difficulty: 1
+ Network: in 0, out 8, total 8
Version: 219900
Time offset (s): 0
Proxy: N/A
Min tx relay fee rate (BTC/kvB): 0.00001000
@@ Wallet: ""@@
Keypool size: 1000
Unlocked until: 0
Transaction fee rate (-paytxfee) (BTC/kvB): 0.00000000
# Balance: 0.02853102
- Warnings: unknown new rules activated (versionbit 28)
```
Abaixo apresentamos outros comandos para obter informações sobre blockchain, mineração, rede, carteira etc.
```
$ bitcoin-cli getblockchaininfo
$ bitcoin-cli getmininginfo
$ bitcoin-cli getnetworkinfo
$ bitcoin-cli getnettotals
$ bitcoin-cli getwalletinfo
```
Por exemplo, `bitcoin-cli getnetworkinfo` fornece uma variedade de informações sobre nossa configuração e nosso acesso a outras redes:
```
$ bitcoin-cli getnetworkinfo
{
"version": 200000,
"subversion": "/Satoshi:0.20.0/",
"protocolversion": 70015,
"localservices": "0000000000000408",
"localservicesnames": [
"WITNESS",
"NETWORK_LIMITED"
],
"localrelay": true,
"timeoffset": 0,
"networkactive": true,
"connections": 10,
"networks": [
{
"name": "ipv4",
"limited": false,
"reachable": true,
"proxy": "",
"proxy_randomize_credentials": false
},
{
"name": "ipv6",
"limited": false,
"reachable": true,
"proxy": "",
"proxy_randomize_credentials": false
},
{
"name": "onion",
"limited": false,
"reachable": true,
"proxy": "127.0.0.1:9050",
"proxy_randomize_credentials": true
}
],
"relayfee": 0.00001000,
"incrementalfee": 0.00001000,
"localaddresses": [
{
"address": "45.79.111.171",
"port": 18333,
"score": 1
},
{
"address": "2600:3c01::f03c:92ff:fecc:fdb7",
"port": 18333,
"score": 1
},
{
"address": "4wrr3ktm6gl4sojx.onion",
"port": 18333,
"score": 4
}
],
"warnings": "Warning: unknown new rules activated (versionbit 28)"
}
```
Vamos testar à vontade qualquer um deles e usar `bitcoin-cli help` se quisermos saber mais informações sobre o que qualquer um deles faz.
## Resumo: Conhecendo Nossa Configuração do Bitcoin
O diretório `~/.bitcoin` contém todos os arquivos, enquanto o `bitcoin-cli help` nos retorna uma variedade de informações de comandos que podem ser usados para obter mais informações sobre como nossa configuração e o Bitcoin funcionam.
## O Que Vem Depois?
Vamos continuar "Compreendendo Nossa Configuração do Bitcoin" na sessão [3.3: Configurando Nossa Carteira](03_3_Setting_Up_Your_Wallet.md).

View File

@ -0,0 +1,131 @@
# 3.3: Configurando Nossa carteira
Agora estamos prontos para começar a brincar com o Bitcoin. Para começar, precisaremos criar um endereço para receber fundos.
## Criando um Endereço
A primeira coisa que precisamos fazer é criar um endereço para recebimento de pagamentos. Podemos fazer isso usando o comando `bitcoin-cli getnewaddress`. Temos que lembrar que se quisermos mais informações sobre este comando, podemos digitar `bitcoin-cli help getnewaddress`. Atualmente, existem três tipos de endereços: Os `legacy` e os dois tipos de endereço SegWit, `p2sh-segwit` e `bech32`. Se não especificarmos qual queremos criar, sempre teremos por padrão o `bech32`.
No entanto, nas próximas sessões, usaremos endereços `legacy`, porque o `bitcoin-cli` teve alguns problemas com suas versões anteriores usando os endereços SegWit e, porque algumas pessoas podem não ser capazes de enviar seus saldos para endereços `bech32`. É improvável que tudo isso seja um problema para nós neste exato momento, mas vamos começar com exemplos de transações que (na maioria das vezes) temos a garantia que irá funcionar.
Podemos exigir um endereço `legacy` como segundo argumento para `getnewaddress` ou com o argumento denominado `addresstype`.
```
$ bitcoin-cli getnewaddress -addresstype legacy
moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B
```
Observe que este endereço começa com "m" (ou às vezes um "n") para significar um endereço legacy na rede Testnet. Seria um "2" para um endereço P2SH ou um "tb1" para um endereço Bech32.
> :link: **TESTNET vs MAINNET:** O endereço Mainnet equivalente começaria com "1" (para Legacy), "3" (para P2SH) ou "bc1" (para Bech32).
Anote cuidadosamente o endereço. Precisaremos utilizá-lo para quando recebermos bitcoins.
> :book: ***O que é um endereço Bitcoin?*** Um endereço Bitcoin é literalmente onde receberemos as moedas. É como um endereço de e-mail, mas para bitcoin. Tecnicamente, é uma chave pública. No entanto, ao contrário de um endereço de e-mail, um endereço Bitcoin deve ser considerado de uso único: Vamos usar para receber fundos apenas _uma vez_. Quando quisermos receber fundos de outra pessoa ou em algum outro momento, precisaremos gerar um novo endereço. Isso é sugerido em grande parte para melhorar nossa privacidade. Toda a blockchain é imutável, o que significa que os exploradores podem observar longas cadeias de transações ao longo do tempo, tornando possível determinar estatisticamente quem é você e quem são os nossos contatos, não importa o quão cuidadoso sejamos. No entanto, se continuarmos reutilizando o mesmo endereço, isso se tornará ainda mais fácil.
> :book: ***O que é uma carteira Bitcoin?*** Ao criar nosso primeiro endereço Bitcoin, também começamos a preencher nossa carteira Bitcoin. Mais precisamente, começamos a preencher o arquivo `wallet.dat` no nosso diretório `~/.bitcoin/testnet3/wallets`. O arquivo `wallet.dat` contém dados sobre preferências e transações, mas mais importante, contém todos os pares de chaves que criamos: A chave pública (que é a fonte do endereço onde receberemos as moedas) e a chave privada (que é como gastamos esses fundos). Na maior parte, não teremos que nos preocupar com a chave privada: O `bitcoind` irá usá-la quando for necessário. No entanto, isso torna o arquivo `wallet.dat` extremamente importante: Se o perdermos, perderemos nossas chaves privadas e, se perdermos as chaves privadas, perderemos nossos fundos!
Com um único endereço em mãos, podemos pular direto para a próxima seção e começar a receber alguns satoshinhos. No entanto, antes de chegarmos lá, vamos discutir brevemente os outros tipos de endereços que encontraremos no futuro e falar sobre alguns outros comandos de carteira que podemos querer usar mais pra frente.
### Conhecendo os Endereços do Bitcoin
Existem três tipos de endereços Bitcoin que podemos criar com o comando RPC `getnewaddress`. Usaremos um endereço `legacy` (P2PKH) aqui, mas iremos utilizar um endereço SegWit (P2SH-SegWit) ou Bech32 na sessão [4.6: Criação de uma transação Segwit](04_6_Creating_a_Segwit_Transaction.md).
Conforme observado acima, a base de um endereço de Bitcoin é uma chave pública: Alguém envia fundos para nossa chave pública e usamos a nossa chave privada para resgatá-la. Simples, não? Exceto que colocar nossa chave pública lá não é algo seguro. No momento, se alguém tiver nossa chave pública, não poderemos recuperar nossa chave privada (e, portanto, nossos fundos). Essa é a base da criptografia, que usa uma função de _trapdoor_ para garantir que só possamos passar da chave privada para a pública, e não vice-versa. Mas o problema é que não sabemos o que o futuro pode nos trazer. Exceto que sabemos que os sistemas de criptografia eventualmente são quebrados pelo avanço implacável da tecnologia, então é melhor não colocar chaves públicas brutas na rede, para prepararmos nossas transações para o futuro.
As transações clássicas do Bitcoin criaram endereços P2PKH que adicionaram uma etapa criptográfica adicional para proteger as chaves públicas.
> :book: ***O que é um endereço legacy (P2PKH)?*** Este é um endereço legado do tipo usado pela antiga rede Bitcoin. Iremos usá-lo em exemplos nas próximas seções. É chamado de endereço Pay to PubKey Hash (ou P2PKH) porque o endereço é um hash de 160 bits de uma chave pública. Usar um hash de sua chave pública como endereço cria um processo de duas etapas onde para gastar os fundos precisamos revelar a chave privada e a chave pública, aumentando assim a segurança futura. Esse tipo de endereço continua sendo importante para receber fundos de pessoas com softwares desatualizados.
Conforme descrito mais detalhadamente na sessão [4.6: Criando uma transação Segwit](04_6_Creating_a_Segwit_Transaction.md), a Guerra pelo Tamanho dos Blocos do final dos anos 10 do Bitcoin resultaram em um novo tipo de endereço: O SegWit. Este é o tipo de endereço preferido atualmente e deve estar totalmente integrado ao Bitcoin-Core neste exato momento.
O SegWit significa simplesmente "Segregated Witness" e é uma maneira de separar as assinaturas da transação do resto dela para reduzir o tamanho da mesma. Alguns endereços SegWit entrarão em alguns de nossos exemplos como endereços de troco, que veremos como endereços que começam com "tb". Isso é bom porque o `bitcoin-cli` suporta inteiramente o seu uso.
Existem dois endereços desse tipo:
> :book: ***O que é um endereço P2SH-SegWit (também conhecido como Nested SegWit)?*** Esta é a primeira geração do SegWit. Ele envolve o endereço SegWit em um hash de script para garantir a compatibilidade com versões anteriores. O resultado cria transações que são cerca de 25% menores (com reduções correspondentes nas taxas de transação).
> :book: ***O que é um endereço Bech32 (também conhecido como SegWit nativo ou como P2WPKH)?*** Esta é a segunda geração do SegWit. Está totalmente descrito em [BIP 173](https://en.bitcoin.it/wiki/BIP_0173). Ele cria transações que são ainda menores, mas mais notavelmente também tem algumas vantagens na criação de endereços que são menos propensos a erro humano e têm algumas correções de erro implícita. Ele _não_ é compatível com versões anteriores como o P2SH-SegWit era e, portanto, algumas pessoas podem não ser capazes de enviar bitcoins para ele.
Existem outros tipos de endereços de Bitcoin, como P2PK (que paga a uma chave pública simples e está obsoleto devido à sua insegurança futura) e P2SH (que paga a um Hash de script e que é usado pelo SegWit e esta aninhado com a primeira geração endereços. Vamos conhecê-lo mais detalhadamente nos próximos capítulos).
## Opcional: Assinando uma Mensagem
Às vezes, precisamos provar que controlamos um endereço Bitcoin (ou melhor, que controlamos a chave privada). Isso é importante porque permite que as pessoas saibam que estão enviando fundos para a pessoa certa. Isso pode ser feito criando uma assinatura com o comando `bitcoin-cli signmessage`, na forma `bitcoin-cli signmessage [endereço] [mensagem]`. Por exemplo:
```
$ bitcoin-cli signmessage "moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B" "Hello, World"
HyIP0nzdcH12aNbQ2s2rUxLwzG832HxiO1vt8S/jw+W4Ia29lw6hyyaqYOsliYdxne70C6SZ5Utma6QY/trHZBI=
```
O resultado é uma assinatura como um retorno.
> :book: ***O que é uma assinatura?*** Uma assinatura digital é uma combinação de uma mensagem e uma chave privada que pode ser desbloqueada com uma chave pública. Como há uma correspondência um-para-um entre os elementos de um par de chaves, o desbloqueio com uma chave pública prova que o assinante controlou a chave privada correspondente.
Outra pessoa pode usar o comando `bitcoin-cli verifymessage` para verificar a assinatura. Ela insere o endereço em questão, a assinatura e a mensagem:
```
$ bitcoin-cli verifymessage "moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B" "HyIP0nzdcH12aNbQ2s2rUxLwzG832HxiO1vt8S/jw+W4Ia29lw6hyyaqYOsliYdxne70C6SZ5Utma6QY/trHZBI=" "Hello, World"
true
```
Se todos eles corresponderem, a outra pessoa saberá que pode transferir fundos com segurança para a pessoa que assinou a mensagem enviando para o endereço.
Se algum golpista estivesse criando assinaturas, isso produziria um erro.
```
$ bitcoin-cli verifymessage "FAKEV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B" "HyIP0nzdcH12aNbQ2s2rUxLwzG832HxiO1vt8S/jw+W4Ia29lw6hyyaqYOsliYdxne70C6SZ5Utma6QY/trHZBI=" "Hello, World"
error code: -3
error message:
Invalid address
```
## Opcional: Fazendo o Dump da Nossa Carteira
Pode parecer perigoso ter todas as chaves privadas insubstituíveis em um único arquivo. É para isso que serve o comando `bitcoin-cli dumpwallet`. Ele permite que façamos uma cópia do nosso arquivo `wallet.dat`:
```
$ bitcoin-cli dumpwallet ~/mywallet.txt
```
O arquivo `mywallet.txt` em nosso diretório home terá uma longa lista de chaves privadas, endereços e outras informações. Lembre-se, ninguém gostaria de colocar esses dados em um arquivo de texto simples, em uma configuração com saldos reais!
Podemos então recuperá-los com o `bitcoin-cli importwallet`.
```
$ bitcoin-cli importwallet ~/mywallet.txt
```
É importante observar que isso requer um node não prunado.
```
$ bitcoin-cli importwallet ~/mywallet.txt
error code: -4
error message:
Importing wallets is disabled when blocks are pruned
```
## Opcional: Visualizando as Chaves Privadas
Às vezes, podemos querer realmente olhar para as chaves privadas associadas aos nossos endereços Bitcoin. Talvez queremos assinar uma mensagem ou gastar bitcoins em uma máquina diferente. Talvez só estamos querendo fazer backup de algumas chaves privadas importantes. Também pode fazer isso com nosso arquivo criado acima, já que ele pode ser lido por humanos.
```
$ bitcoin-cli dumpwallet ~/mywallet.txt
{
"filename": "/home/standup/mywallet.txt"
}
```
Mais provavelmente, desejamos apenas examinar a chave privada associada a um endereço específico. Isso pode ser feito com o comando `bitcoin-cli dumpprivkey`.
```
$ bitcoin-cli dumpprivkey "moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B"
cTv75T4B3NsG92tdSxSfzhuaGrzrmc1rJjLKscoQZXqNRs5tpYhH
```
Podemos salvar essa chave em um local seguro, de preferência em algum lugar sem conexão com a Internet.
Também podemos importar qualquer chave privada, de um dump de carteira ou um dump da chave individual, da seguinte maneira:
```
$ bitcoin-cli importprivkey cW4s4MdW7BkUmqiKgYzSJdmvnzq8QDrf6gszPMC7eLmfcdoRHtHh
```
Novamente, é esperado que isso exija um node não prunado. Isso provavelmente vai demorar um pouco, já que o `bitcoind` precisa reler todas as transações anteriores, para ver se há alguma nova.
> :information_source: **NOTA:** Muitas carteiras modernas preferem [códigos mnemônicos](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) para gerar as seeds necessárias para criar as chaves privadas. Esta metodologia não é usada pelo `bitcoin-cli`, então não seremos capazes de gerar listas de palavras para lembrar das nossas chaves privadas.
_Nós digitamos aquele endereço Bitcoin que gerou, enquanto assinávamos uma mensagem e agora estamos fazendo o dump as chaves. Se por acaso achar que isso é muito complicado, os autores e tradutores também concordam com isso. Também estamos sujeitos a erros, um tópico que abordaremos na próxima sessão._
## Resumo: Configurando Nossa carteira
Precisamos criar um endereço para receber fundos. Nosso endereço é armazenado em uma carteira, da qual podemos fazer o backup. Podemos fazer muito coisas com nosso endereço, como fazer o dump da nossa chave privada ou usá-la para assinar mensagens. Mas, realmente, criar esse endereço é _tudo_ que precisaremos fazer para receber alguns satoshinhos.
## O Que Vem Depois?
Vamos dar uma pausa no capítulo "Compreendendo Nossa Configuração do Bitcoin" com o [Prefácio: Usando Variáveis de Linha de Comando](03_3__Interlude_Using_Command-Line_Variables.md).

View File

@ -0,0 +1,40 @@
# Usando Variáveis de Linha de Comando
A sessão anterior demonstrou vários comandos de linha de comando usados sem ofuscação ou interferência. No entanto, geralmente essa não é a melhor maneira de executar o Bitcoin usando a linha de comando. Como estamos lidando com variáveis longas, complexas e difíceis de serem lidas, é fácil cometer um erro se estivermos copiando essas variáveis (ou, perder alguns satoshis, se as digitarmos manualmente). Como essas variáveis podem significar a diferença entre receber e perder dinheiro quando usarmos a Mainnet, não _queremos_ cometer erros. Por esses motivos, sugerimos enfaticamente o uso de variáveis de linha de comando para salvar endereços, assinaturas ou outras cadeias de informações longas sempre que isso for razoável.
Se estiver usando `bash`, podemos salvar as informações em uma variável como esta:
```
$ VARIABLE=$(command)
```
Esta é uma substituição de um comando simples, o equivalente a `VARIABLE = command`. O comando entre parênteses é executado e, em seguida, atribuído à VARIABLE.
Para criar um novo endereço, seria assim:
```
$ unset NEW_ADDRESS_1
$ NEW_ADDRESS_1=$(bitcoin-cli getnewaddress "" legacy)
```
Esses comandos limpam a variável NEW_ADDRESS_1, apenas para ter certeza, e então a preenchem com os resultados do comando `bitcoin-cli getnewaddress`.
Podemos então usar o comando `echo` do shell para vermos nosso (novo) endereço:
```
$ echo $NEW_ADDRESS_1
mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE
```
Como nosso endereço está em uma variável, agora podemos assinar facilmente uma mensagem para esse endereço, sem nos preocupar em digitar o endereço incorretamente. É claro que também salvaremos essa assinatura em uma variável!
```
$ NEW_SIG_1=$(bitcoin-cli signmessage $NEW_ADDRESS_1 "Hello, World")
$ echo $NEW_SIG_1
IPYIzgj+Rg4bxDwCyoPiFiNNcxWHYxgVcklhmN8aB2XRRJqV731Xu9XkfZ6oxj+QGCRmTe80X81EpXtmGUpXOM4=
```
O restante deste tutorial usará esse estilo de armazenamento de informações quando for mais prático.
> :book: ***Quando não é prático usar variáveis de linha de comando?*** Variáveis de linha de comando não são práticas se precisarmos usar as informações em algum lugar diferente da linha de comando. Por exemplo, salvar a assinatura pode não ser útil se tivermos que enviá-la a outra pessoa por e-mail. Além disso, alguns comandos futuros produzirão objetos JSON ao invés de informações simples, e as variáveis não podem ser usadas para capturar essas informações, ao menos não sem um _pouco_ mais de mais trabalho.
## Resumo: Usando Variáveis de Linha de Comando
Variáveis de shell podem ser usadas para manter longas strings, minimizando as chances de erros.
## O Que Vem Depois?
Vamos continuar "Compreendendo Nossa Configuração do Bitcoin" na sessão [3.4: Recebendo uma Transação](03_4_Receiving_a_Transaction.md).

View File

@ -0,0 +1,316 @@
# 3.4: Recebendo uma Transação
Agora estamos prontos para receber dinheiro no endereço que configuramos.
## Pegando um Pouco de Dinheiro
Para fazermos qualquer coisa a mais, precisamos de dinheiro. Na Testnet, isso é feito por meio de _faucets_. Como o dinheiro é de mentira, basta irmos a um faucet e pedirmos um pouco de dinheiro que ele será enviado para nós. Sugerimos usar o faucet em https://testnet-faucet.mempool.co/, https://bitcoinfaucet.uo1.net/ ou https://testnet.coinfaucet.eu/en/. Se eles não estiverem disponíveis por algum motivo, podemos pesquisar por "bitcoin testnet faucet" na internet e encontrar outros.
Para usarmos um faucet, geralmente precisamos acessar uma URL e copiar e colar nosso endereço. É importante observamos que este é um daqueles casos em que não seremos capazes de usar variáveis de linha de comando, infelizmente. Posteriormente, será criada uma transação que enviará dinheiro da faucet para nós.
> :book: ***O que é uma transação?*** Uma transação é uma troca de bitcoins. O proprietário de alguns bitcoins usa sua chave privada para acessar essas moedas e, em seguida, bloqueia a transação usando a chave pública do destinatário.
> :link: **TESTNET vs MAINNET:** Infelizmente, não existem faucets na vida real. Se estivéssemos usando a Mainnet, precisaríamos realmente comprar bitcoins em uma exchange ou em um caixa eletrônico, ou precisaríamos que alguém os enviasse alguns satoshinhos. A vida na Testnet é muito mais fácil.
## Verificando o Nosso Dinheiro
Depois de solicitarmos nosso dinheiro, devemos ser capazes de verificá-lo com o comando `bitcoin-cli getbalance`:
```
$ bitcoin-cli getbalance
0.00000000
```
Mas espere, não há nenhum saldo ainda!?
Bem-vindo ao mundo da latência do Bitcoin. O problema é que nossa transação ainda não foi gravada no bloco!
> :book: ***O que é um bloco?*** As transações são transmitidas pela rede e reunidas em blocos pelos mineradores. Esses blocos são protegidos com uma prova de trabalho matemática (em inglês, _proof-of-work_, ou PoW), que prova que o poder de computação foi gasto como parte da criação do bloco. É essa prova de trabalho (multiplicada por muitos blocos, cada um construído sobre o último) que mantém o Bitcoin seguro.
> :book: ***O que é um minerador?*** Um minerador é um participante na rede Bitcoin que trabalha para criar blocos. É um trabalho remunerado: quando um minerador cria um bloco com sucesso, ele recebe uma recompensa única mais as taxas pelas transações em seu bloco. A mineração é um grande negócio. Os mineradores tendem a utilizar hardwares especiais, projeto de maneiras que tornam mais provável que sejam capazes de criar blocos. Eles também tendem a fazer parte de pools de mineração (_mining pools_), onde todos os mineradores concordam em dividir as recompensas quando um deles cria um bloco com sucesso.
Felizmente, `bitcoin-cli getunconfirmedbalance` ainda deve mostrar nosso saldo atualizado, desde que a transação inicial tenha sido criada:
```
$ bitcoin-cli getunconfirmedbalance
0.01010000
```
Se ainda estiver mostrando um zero, provavelmente estamos avançando neste tutorial rápido demais. Espere alguns segundos. As moedas devem aparecer não confirmadas e, em seguida, serão rapidamente confirmadas. Observe que uma moeda pode passar de um saldo não confirmado para o confirmado quase imediatamente, portanto, devemos nos certificar de verificar ambos. No entanto, se o `getbalance` e o `getunconfirmedbalance` ainda mostrarem zero nos próximos dez minutos, então provavelmente há algo errado com o faucet e precisaremos escolher outra.
### Ganhando Confiança no Nosso Dinheiro
Podemos usar `bitcoin-cli getbalance" * "[n]`, onde substituímos `[n]` por um inteiro, para ver se um saldo confirmado tem 'n' blocos de profundidade.
> :book: ***O que é a profundidade do bloco?*** Depois que um bloco é construído e confirmado, outro bloco é construído em cima dele e então outro... Como este é um processo estocástico, há alguma chance de reversão quando um bloco ainda é novo. Portanto, um bloco deve ser "enterrado" vários blocos na blockchain antes que possamos nos sentir totalmente confiantes com nossos fundos. Cada um desses blocos tende a ser construído em uma média de 10 minutos, então normalmente leva cerca de uma hora para uma transação confirmada receber seis blocos de profundidade, que é a medida para completa confiança no Bitcoin.
O seguinte mostra que nossas transações foram confirmadas uma vez, mas não duas vezes:
```
$ bitcoin-cli getbalance "*" 1
0.01010000
$ bitcoin-cli getbalance "*" 2
0.00000000
```
Obviamente, a cada dez minutos mais ou menos essa profundidade aumentará.
É claro que, na Testnet, ninguém está tão preocupado com a confiabilidade dos fundos. Nós poderemos gastar nosso dinheiro assim que for confirmado.
## Verificando Nossa Carteira
O comando `bitcoin-cli getwalletinfo` fornece mais informações sobre o saldo da nossa carteira:
```
$ bitcoin-cli getwalletinfo
{
"walletname": "",
"walletversion": 169900,
"balance": 0.01010000,
"unconfirmed_balance": 0.00000000,
"immature_balance": 0.00000000,
"txcount": 2,
"keypoololdest": 1592335137,
"keypoolsize": 999,
"hdseedid": "fdea8e2630f00d29a9d6ff2af7bf5b358d061078",
"keypoolsize_hd_internal": 1000,
"paytxfee": 0.00000000,
"private_keys_enabled": true,
"avoid_reuse": false,
"scanning": false
}
```
## Descobrindo o ID da Nossa Transação
Nosso dinheiro entrou na nossa carteira por meio de uma transação. Podemos descobrir o ID da transação (txid) com o comando `bitcoin-cli listtransactions`:
```
$ bitcoin-cli listtransactions
[
{
"address": "mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
"category": "receive",
"amount": 0.01000000,
"label": "",
"vout": 1,
"confirmations": 1,
"blockhash": "00000000000001753b24411d0e4726212f6a53aeda481ceff058ffb49e1cd969",
"blockheight": 1772396,
"blockindex": 73,
"blocktime": 1592600085,
"txid": "8e2ab10cabe9ec04ed438086a80b1ac72558cc05bb206e48fc9a18b01b9282e9",
"walletconflicts": [
],
"time": 1592599884,
"timereceived": 1592599884,
"bip125-replaceable": "no"
},
{
"address": "mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
"category": "receive",
"amount": 0.00010000,
"label": "",
"vout": 0,
"confirmations": 1,
"blockhash": "00000000000001753b24411d0e4726212f6a53aeda481ceff058ffb49e1cd969",
"blockheight": 1772396,
"blockindex": 72,
"blocktime": 1592600085,
"txid": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
"walletconflicts": [
],
"time": 1592599938,
"timereceived": 1592599938,
"bip125-replaceable": "no"
}
]
```
Isto mostra duas transações (`8e2ab10cabe9ec04ed438086a80b1ac72558cc05bb206e48fc9a18b01b9282e9`) e (` ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36`) para uma quantidade específica (`0.01000000` e `0.00010000`), que foram recebidas (`receive`) pelo mesmo endereço em nossa carteira (` mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE`) . À propósito, isso é uma boa prática para as chaves: devemos usar um novo endereço para cada Bitcoin que recebermos. Nesse caso, ficamos impacientes porque a primeira faucet parecia não estar funcionando.
Podemos acessar informações semelhantes com o comando `bitcoin-cli listunspent`, mas ele só mostra as transações para o dinheiro que não gastamos. Eles são chamados de UTXOs e serão de vital importância quando estivermos enviando dinheiro de volta para o mundo Bitcoin:
```
$ bitcoin-cli listunspent
[
{
"txid": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
"vout": 0,
"address": "mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
"label": "",
"scriptPubKey": "76a9141b72503639a13f190bf79acf6d76255d772360b788ac",
"amount": 0.00010000,
"confirmations": 1,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/1']02fd5740996d853ea51a6904cf03257fc11204b0179f344c49739ec5b20b39c9ba)#62rud39c",
"safe": true
},
{
"txid": "8e2ab10cabe9ec04ed438086a80b1ac72558cc05bb206e48fc9a18b01b9282e9",
"vout": 1,
"address": "mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
"label": "",
"scriptPubKey": "76a9141b72503639a13f190bf79acf6d76255d772360b788ac",
"amount": 0.01000000,
"confirmations": 1,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/1']02fd5740996d853ea51a6904cf03257fc11204b0179f344c49739ec5b20b39c9ba)#62rud39c",
"safe": true
}
]
```
Observe que os bitcoins não são simplesmente uma bagunça homogênea de dinheiro enfiado no nosso bolso. Cada transação individual que recebemos ou enviamos é colocada no livro razão da blockchain imutável, em um bloco. Podemos ver essas transações individuais quando olhamos para o nosso dinheiro não gasto. Isso significa que os gastos com bitcoins não são tão anônimos quanto pensamos. Embora os endereços sejam bastante privados, as transações podem ser examinadas à medida que entram e saem dos endereços. Isso torna a privacidade vulnerável à análise estatística. Também introduz uma potencial de não fungibilidade para os bitcoins, já que se pode rastrear uma série de transações, mesmo se não puder rastrear um "bitcoin" específico.
>: book: ***Por que todas essas quantidades de bitcoin em frações?*** Os bitcoins são produzidos lentamente e, portanto, há relativamente poucos em circulação. Como resultado, cada bitcoin na rede principal valem relativamente bastante (pouco mais de 9 mil dólares no momento em que este livro foi escrito). Isso significa que as pessoas geralmente trabalham com frações. Na verdade, o 0,0101 em moedas Testnet valeria cerca de $100 se eles estivessem na rede principal. Por esse motivo, surgiram nomes para quantidades menores de bitcoins, incluindo milibitcoins ou mBTCs (um milésimo de um bitcoin), microbitcoins ou bits ou μBTCs (um milionésimo de um bitcoin) e satoshis (um centésimo de milionésimo de um bitcoin).
## Examinando Nossa Transação
Podemos adquirir maiores informações em uma transação com o comando `bitcoin-cli gettransaction`:
```
$ bitcoin-cli gettransaction "8e2ab10cabe9ec04ed438086a80b1ac72558cc05bb206e48fc9a18b01b9282e9"
{
"amount": 0.01000000,
"confirmations": 1,
"blockhash": "00000000000001753b24411d0e4726212f6a53aeda481ceff058ffb49e1cd969",
"blockheight": 1772396,
"blockindex": 73,
"blocktime": 1592600085,
"txid": "8e2ab10cabe9ec04ed438086a80b1ac72558cc05bb206e48fc9a18b01b9282e9",
"walletconflicts": [
],
"time": 1592599884,
"timereceived": 1592599884,
"bip125-replaceable": "no",
"details": [
{
"address": "mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
"category": "receive",
"amount": 0.01000000,
"label": "",
"vout": 1
}
],
"hex": "0200000000010114d04977d1b0137adbf51dd5d79944b9465a2619f3fa7287eb69a779977bf5800100000017160014e85ba02862dbadabd6d204fcc8bb5d54658c7d4ffeffffff02df690f000000000017a9145c3bfb36b03f279967977ca9d1e35185e39917788740420f00000000001976a9141b72503639a13f190bf79acf6d76255d772360b788ac0247304402201e74bdfc330fc2e093a8eabe95b6c5633c8d6767249fa25baf62541a129359c202204d462bd932ee5c15c7f082ad7a6b5a41c68addc473786a0a9a232093fde8e1330121022897dfbf085ecc6ad7e22fc91593414a845659429a7bbb44e2e536258d2cbc0c270b1b00"
}
```
O comando `gettransaction` detalhará transações que estão na nossa carteira, como esta, que nos foi enviada.
Observando o `gettransaction` temos dois argumentos opcionais:
```
$ bitcoin-cli help gettransaction
gettransaction "txid" ( include_watchonly verbose )
Get detailed information about in-wallet transaction <txid>
Arguments:
1. txid (string, required) The transaction id
2. include_watchonly (boolean, optional, default=true for watch-only wallets, otherwise false) Whether to include watch-only addresses in balance calculation and details[]
3. verbose (boolean, optional, default=false) Whether to include a `decoded` field containing the decoded transaction (equivalent to RPC decoderawtransaction)
```
Configurando esses dois como `true` ou `false`, podemos escolher se queremos incluir endereços "watch-only" no resultado (com os quais não nos importamos) ou vermos um resultado mais extenso (o que queremos).
Aqui estão os dados quando definimos `include_watchonly` como `false` e `verbose` como `true`.
```
$ bitcoin-cli gettransaction "8e2ab10cabe9ec04ed438086a80b1ac72558cc05bb206e48fc9a18b01b9282e9" false true
{
"amount": 0.01000000,
"confirmations": 3,
"blockhash": "00000000000001753b24411d0e4726212f6a53aeda481ceff058ffb49e1cd969",
"blockheight": 1772396,
"blockindex": 73,
"blocktime": 1592600085,
"txid": "8e2ab10cabe9ec04ed438086a80b1ac72558cc05bb206e48fc9a18b01b9282e9",
"walletconflicts": [
],
"time": 1592599884,
"timereceived": 1592599884,
"bip125-replaceable": "no",
"details": [
{
"address": "mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
"category": "receive",
"amount": 0.01000000,
"label": "",
"vout": 1
}
],
"hex": "0200000000010114d04977d1b0137adbf51dd5d79944b9465a2619f3fa7287eb69a779977bf5800100000017160014e85ba02862dbadabd6d204fcc8bb5d54658c7d4ffeffffff02df690f000000000017a9145c3bfb36b03f279967977ca9d1e35185e39917788740420f00000000001976a9141b72503639a13f190bf79acf6d76255d772360b788ac0247304402201e74bdfc330fc2e093a8eabe95b6c5633c8d6767249fa25baf62541a129359c202204d462bd932ee5c15c7f082ad7a6b5a41c68addc473786a0a9a232093fde8e1330121022897dfbf085ecc6ad7e22fc91593414a845659429a7bbb44e2e536258d2cbc0c270b1b00",
"decoded": {
"txid": "8e2ab10cabe9ec04ed438086a80b1ac72558cc05bb206e48fc9a18b01b9282e9",
"hash": "d4ae2b009c43bfe9eba96dcd16e136ceba2842df3d76a67d689fae5975ce49cb",
"version": 2,
"size": 249,
"vsize": 168,
"weight": 669,
"locktime": 1772327,
"vin": [
{
"txid": "80f57b9779a769eb8772faf319265a46b94499d7d51df5db7a13b0d17749d014",
"vout": 1,
"scriptSig": {
"asm": "0014e85ba02862dbadabd6d204fcc8bb5d54658c7d4f",
"hex": "160014e85ba02862dbadabd6d204fcc8bb5d54658c7d4f"
},
"txinwitness": [
"304402201e74bdfc330fc2e093a8eabe95b6c5633c8d6767249fa25baf62541a129359c202204d462bd932ee5c15c7f082ad7a6b5a41c68addc473786a0a9a232093fde8e13301",
"022897dfbf085ecc6ad7e22fc91593414a845659429a7bbb44e2e536258d2cbc0c"
],
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.01010143,
"n": 0,
"scriptPubKey": {
"asm": "OP_HASH160 5c3bfb36b03f279967977ca9d1e35185e3991778 OP_EQUAL",
"hex": "a9145c3bfb36b03f279967977ca9d1e35185e399177887",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"2N1ev1WKevSsdmAvRqZf7JjvDg223tPrVCm"
]
}
},
{
"value": 0.01000000,
"n": 1,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 1b72503639a13f190bf79acf6d76255d772360b7 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9141b72503639a13f190bf79acf6d76255d772360b788ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE"
]
}
}
]
}
}
```
Agora podemos ver todas as informações sobre a transação, incluindo todas as entradas ("vin") e todas as saídas ("vout). Uma das coisas interessantes a se notar é que, embora tenhamos recebido 0,01 BTC na transação, outro 0.01010143 foi enviado para outro endereço. Provavelmente era um endereço de troco, um conceito que será explorado na próxima seção. É bastante comum uma transação ter várias entradas e/ou várias saídas.
Existe outro comando, `getrawtransaction`, que nos permite ver as transações que não estão em nossa carteira. No entanto, requer que tenhamos um node não prunado e `txindex = 1` em nosso arquivo `bitcoin.conf`. A menos que tenhamos uma necessidade séria de informações que não estão em nossa carteira, provavelmente é melhor usarmos um explorador de Bitcoin para esse tipo de coisa.
## Opcional: Usando um Explorador de Blocos
Até mesmo olhar para as informações detalhadas de uma transação pode ser um pouco intimidante. O principal objetivo deste tutorial é ensinar como lidar com transações brutas da linha de comando, mas ficaremos felizes em falar sobre outras ferramentas quando elas forem aplicáveis. Uma dessas ferramentas é um explorador de blocos, que podemos usar para ver as transações de um navegador web em um formato muito mais amigável.
Atualmente, nosso explorador de bloco preferido é [https://mempool.space/](https://mempool.space/).
Podemos usá-lo para procurar transações para um endereço:
[https://mempool.space/pt/testnet/address/mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE](https://mempool.space/pt/testnet/address/mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE)
Também podemos usá-lo para ver transações individuais:
[https://mempool.space/pt/testnet/tx/8e2ab10cabe9ec04ed438086a80b1ac72558cc05bb206e48fc9a18b01b9282e9](https://mempool.space/pt/testnet/tx/8e2ab10cabe9ec04ed438086a80b1ac72558cc05bb206e48fc9a18b01b9282e9)
Um explorador de bloco geralmente não fornece mais informações do que uma linha de comando em uma transação bruta; ele apenas destaca as informações importantes e junta as peças do quebra-cabeça, incluindo as taxas de transação por trás de uma transação - outro conceito que abordaremos nas próximas seções.
## Resumo: Recebendo uma Transação
As faucets nos vão dar dinheiro na Testnet. O dinheiro vem como transações brutas, que podem ser examinadas com `gettransaction` ou um explorador de blocos. Assim que recebermos uma transação, poderemos vê-la em nosso saldo e em nossa carteira.
## O Que Vem Depois?
Para sabermos como os endereços são descritos, para que eles possam ser transferidos ou transformados em partes de uma assinatura múltipla, podemos consultar [§3.5: Compreendendo o Descritor](03_5_Understanding_the_Descriptor.md).
Mas se isso for muito aprofundado, podemos continuar no [Capítulo Quatro: Enviando Transações no Bitcoin](04_0_Sending_Bitcoin_Transactions.md).

View File

@ -0,0 +1,149 @@
# 3.5: Compreendendo o Descritor
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. Cuidado, leitor.
Você deve ter notado o estranho campo `desc:` no comando `listunspent` da seção anterior. Aqui está o que está acontecendo (e como ele pode ser usado para transferir endereços).
> :warning: **AVISO DE VERSÃO:** Esta é uma inovação do Bitcoin Core v0.17.0 que continuou a ser expandida através do Bitcoin Core 0.20.0. A maioria dos comandos nesta seção são de 0.17.0, mas o `importmulti` atualizado que suporta descritores é de 0.18.0.
## Entendendo Sobre a Transferência de Endereços
A maior parte deste curso presume que estejamos trabalhando inteiramente a partir de um único node onde gerenciamos nossa própria carteira, enviando e recebendo pagamentos com os endereços criados por essa carteira. No entanto, não é necessariamente assim que funciona o ecossistema Bitcoin por completo. Nesse caso, é mais provável que movamos endereços entre carteiras e até mesmo configuremos carteiras para vigiar fundos controlados por carteiras diferentes.
É aí que entram os descritores. Eles são mais úteis se estivermos interagindo com _outro_ software que não seja o Bitcoin Core, e se realmente precisamos do apoio deste tipo de função de compatibilidade: podemos consultar a seção [§6.1](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/pt/06_1_Sending_a_Transaction_to_a_Multisig.md) para um exemplo do mundo real de como usar a capacidade total dos descritores é fundamental.
Mover endereços entre carteiras costumava focar em `xpub` e `xprv`, e eles ainda possuem suporte.
> :book: ***O que é xprv?*** Uma chave privada estendida (_xtended private key_). Esta é a combinação de uma chave privada e um código de cadeia. É uma chave privada da qual uma sequência inteira de chaves privadas filhas pode ser derivada.
> :book: ***O que é xpub?*** Uma chave pública estendida (_xtended public key_). Esta é a combinação de uma chave pública e um código de cadeia. É uma chave pública da qual uma sequência inteira de chaves públicas filhas pode ser derivada.
O fato de que podemos ter uma "sequência inteira de chaves filhas" revela o fato de que "xpub" e "xprv" não são chaves padrão como falamos até agora. Em vez disso, são chaves hierárquicas que podem ser usadas para criar molhos inteiros de chaves, baseadas na ideia de carteiras HD.
> :book: ***O que é uma Carteira HD?*** A maioria das carteiras modernas é construída com base no [BIP32: Hierarchical Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). Este é um design hierárquico em que uma única seed pode ser usada para gerar uma sequência completa de chaves. A carteira inteira pode então ser restaurada a partir dessa seed, em vez de exigir a restauração de cada chave privada.
> :book: ***O que é um caminho de derivação?*** Quando temos chaves hierárquicas, precisamos ser capazes de definir chaves individuais como descendentes de uma semente. Por exemplo, `[0]` é a 0ª chave, `[0/1]` é o primeiro filho da 0ª chave, `[1/0/1]` é o primeiro neto do filho zero da 1ª chave. Algumas chaves também contêm um `'` após o número, para mostrar que estão protegidas, o que as protege de um ataque específico que pode ser usado para derivar uma `xprv` de uma `xpub`. Não precisamos nos preocupar com os detalhes, a não ser o fato de que esses `'`s causarão problemas de formatação ao trabalhar na linha de comando.
> :information_source: **NOTA:** um caminho de derivação define uma chave, o que significa que uma chave representa um caminho de derivação. Eles são equivalentes. No caso de um descritor, o caminho de derivação permite ao `bitcoind` saber de onde veio a chave que segue no descritor!
`xpubs` e `xprvs` provaram ser insuficientes quando os tipos de chaves públicas multiplicadas sob a [expansão SegWit](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/04_6_Creating_a_Segwit_Transaction.md), portanto essa é a necessidade de "descritores de saída".
> :book: ***O que é um descritor de saída?*** Uma descrição precisa de como derivar um endereço Bitcoin de uma combinação de uma função com uma ou mais entradas para essa função.
A introdução de funções nos descritores é o que os torna poderosos, porque eles podem ser usados para transferir todos os tipos de endereços, desde os endereços legados com os quais estamos trabalhando agora até os endereços Segwit e multisig que encontraremos no futuro. Uma função individual corresponde a um determinado tipo de endereço e se correlaciona com regras específicas para gerar esse endereço.
## Capturando um Descritor
Descritores são visíveis em vários comandos, como por exemplo `listunspent` e `getaddressinfo`:
```
$ bitcoin-cli getaddressinfo ms7ruzvL4atCu77n47dStMb3of6iScS8kZ
{
"address": "ms7ruzvL4atCu77n47dStMb3of6iScS8kZ",
"scriptPubKey": "76a9147f437379bcc66c40745edc1891ea6b3830e1975d88ac",
"ismine": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk",
"iswatchonly": false,
"isscript": false,
"iswitness": false,
"pubkey": "03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388",
"iscompressed": true,
"ischange": false,
"timestamp": 1592335136,
"hdkeypath": "m/0'/0'/18'",
"hdseedid": "fdea8e2630f00d29a9d6ff2af7bf5b358d061078",
"hdmasterfingerprint": "d6043800",
"labels": [
""
]
}
```
Neste caso, o descritor é `pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk`.
## Compreendendo um Descritor
Um descritor é composto de várias partes:
```
função([caminho-de-derivação]chave)#checksum
```
Vamos explicar o que tudo isso significa:
* **Função.** A função que é usada para criar um endereço a partir dessa chave. Nestes casos, é `pkh`, que é o endereço padrão P2PKH legado que encontramos em [§3.3: Configurando Nossa Carteira](03_3_Setting_Up_Your_Wallet.md). Da mesma forma, um endereço P2WSH SegWit usaria `wsh` e um endereço P2WPKH usaria `wpkh`;
* **Caminho de Derivação.** Descreve qual parte de uma carteira HD está sendo exportada. Neste caso, é uma seed com a impressão digital `d6043800` e então o 18º filho do 0º filho do 0º filho (`0 '/ 0' / 18'`) dessa seed. Também pode haver uma derivação adicional após a chave: `função([caminho-de-derivação]chave/mais-derivação)#checksum`.
* É importante notar aqui que, se algum dia recebermos um caminho de derivação sem uma impressão digital, poderemos inventá-lo. Acontece que, se houver um existente, devemos usá-lo, porque se algum dia voltarmos para o dispositivo que criou a impressão digital, precisaremos ter o mesmo;
* **Chave**. A chave ou as chaves que estão sendo transferidas. Isso pode ser algo tradicional como uma `xpub` ou `xprv`, pode ser apenas uma chave pública para um endereço, como neste caso, pode ser um conjunto de endereços para uma multi-assinatura, ou pode ser outra coisa. Estes são os dados principais: a função explica o que fazer com eles;
* **Checksum**. Os descritores são feitos para poderem ser transferidos por humanos. Esta soma de verificação (checksum) garante que o fizemos corretamente;
Podemos ver [Informações do Suporte do Bitcoin Core ao Descritor](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md) para maiores informações.
## Examinando um Descritor
Podemos examinar um descritor com o comando RPC `getdescriptorinfo`:
```
$ bitcoin-cli getdescriptorinfo "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk"
{
"descriptor": "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk",
"checksum": "4ahsl9pk",
"isrange": false,
"issolvable": true,
"hasprivatekeys": false
}
```
Observe que ele retorna um checksum. Se algum dia recebermos um descritor sem um checksum, podemos encontrá-lo com este comando:
```
$ bitcoin-cli getdescriptorinfo "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)"
{
"descriptor": "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk",
"checksum": "4ahsl9pk",
"isrange": false,
"issolvable": true,
"hasprivatekeys": false
}
```
Além de nos dar o checksum, esse comando também verifica a validade do descritor e nos dá informações úteis, como se o descritor contém chaves privadas.
Um dos poderes de um descritor é a capacidade de derivar um endereço de forma padrão. Isto é feito com o RPC `deriveaddresses`.
```
$ bitcoin-cli deriveaddresses "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk"
[
"ms7ruzvL4atCu77n47dStMb3of6iScS8kZ"
]
```
Podemos observar que ele nos retorna o endereço inicial (como deveria).
## Importando um Descritor
Mas a coisa realmente importante sobre um descritor é que podemos levá-lo a outra máquina (remota) e importá-lo. Isto é feito com o RPC `importmulti` usando a opção `desc`:
```
remote$ bitcoin-cli importmulti '[{"desc": "pkh([d6043800/0'"'"'/0'"'"'/18'"'"']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk", "timestamp": "now", "watchonly": true}]'
[
{
"success": true
}
]
```
Primeiro, podemos notar nosso primeiro uso muito feio de aspas. Toda `'` no caminho de derivação pode ser substituído com `'"'"'`. Devemos esperar fazer isso se estivermos manipulando um descritor que contenha um caminho de derivação. (Outra opção é trocar o `'` com um `h` de "hardened", mas isto irá alterar nosso checksum, então caso tenhamos essa preferência pela facilidade de uso, precisaremos de um novo checksum com o `getdescriptorinfo`.)
Segundo, podemos notar que o marcamos como `watchonly`. Isso ocorre porque sabemos que é uma chave pública, então não podemos usá-la para gastar fundos. Se tivéssemos esquecido de colocar esta sinalização, `importmulti` teria dito algo como o seguinte: `Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag.`.
> :book: ***O que é um endereço watch-only?*** Um endereço watch-only nos permite atentar a transações de certo endereço (ou para toda uma família de endereços se tivermos usado uma `xpub`), mas não nos permite gastarmos fundos destes endereços.
Usando `getaddressbylabel`, podemos ver que nosso endereço foi importado corretamente na nossa máquina remota!
```
remote$ bitcoin-cli getaddressesbylabel ""
{
"ms7ruzvL4atCu77n47dStMb3of6iScS8kZ": {
"purpose": "receive"
}
}
```
## Resumo: Compreendendo o Descritor
Descritores nos permitem passar chaves públicas e privadas entre carteiras, mas mais do que isso, nos permitem definir endereços de forma correta e precisa, além de derivar endereços de tipos diversos a partir de um formato descritivo e padronizado.
> :fire: ***Qual é o poder dos descritores?*** Descritores nos permitem importar e exportar chaves e seeds. O que é excelente se queremos movê-las entre carteiras diferentes. Como um desenvolvedor, eles também nos permitem construir o tipo preciso de endereços que queremos criar. Por exemplo, nós os utilizamos na [FullyNoded 2](https://github.com/BlockchainCommons/FullyNoded-2/blob/master/Docs/How-it-works.md) para gerarmos um multisig de três seeds.
Faremos uso real dos descritores na seção [§7.3](07_3_Integrating_with_Hardware_Wallets.md), quando estivermos importando endereços de uma hardware wallet.
## O Que Vem Depois?
Vamos avançar no "bitcoin-cli" com o [Capítulo Quatro: Enviando Transações no Bitcoin](04_0_Sending_Bitcoin_Transactions.md).

View File

@ -0,0 +1,29 @@
# Capítulo 4: Enviando Transações no Bitcoin
Este capítulo descreve três métodos diferentes para enviar bitcoins para endereços P2PKH normais à partir da linha de comando, usando apenas o ```bitcoin-cli```.
## Objetivos deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Decidir como enviar dinheiro usando o Bitcoin;
* Criar uma transação bruta;
* Usar aritmética para calcular as taxas.
Os objetivos secundários incluem a capacidade de:
* Compreender transações e taxas de transação;
* Entender as transações ```legacy``` e ```SegWit```;
* Usar métodos básicos para enviar dinheiro;
* Usar métodos de cálculo de taxa automática para enviar dinheiro;
* Entender os perigos de transações brutas.
## Tabela de Conteúdo
* [Seção 1: Enviando Moedas da Maneira Fácil](04_1_Sending_Coins_The_Easy_Way.md)
* [Seção 2: Criando uma Transação Bruta](04_2_Creating_a_Raw_Transaction.md)
* [Prefácio: Usando JQ](04_2__Interlude_Using_JQ.md)
* [Seção 3: Criando uma Transação Bruta com Argumentos Nomeados](04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md)
* [Seção 4: Enviando Moedas com Transações Brutas](04_4_Sending_Coins_with_a_Raw_Transaction.md)
* [Seção 5: Enviando Moedas com Transações Brutas Automatizadas](04_5_Sending_Coins_with_Automated_Raw_Transactions.md)
* [Seção 6: Criando uma Transação SegWit](04_6_Creating_a_Segwit_Transaction.md)

View File

@ -0,0 +1,102 @@
# 4.1: Enviando Moedas da Maneira Fácil
O ```bitcoin-cli``` oferece três principais maneiras de enviar bitcoins: Utilizando um simples comando; Utilizando uma transação bruta e; Utilizando uma transação bruta com cálculos. Cada uma possui seus prós e contras. Este primeiro método de envio será o mais simples.
## Definindo Nossa Taxa de Transação
Antes de enviar qualquer bitcoin pela rede, devemos pensar sobre as taxas de transação que iremos pagar.
> :book: ***O que é uma taxa de transação?*** Não existe almoço grátis. Os mineradores adicionam as transações nos blocos porque são pagos para fazer isso. Eles não apenas são pagos pela rede para criar o bloco, mas também são pagos pelas pessoas que realizam as transações para incluí-las na blockchain. Se não pagarmos a taxa, nossa transação pode ficar travada... para sempre (ou, até que seja salva por alguns dos truques que falaremos no [capítulo cinco](05_0_Controlling_Bitcoin_Transactions.md)).
Ao usar métodos simples e automatizados para criar transações, conforme descrito aqui e na sessão [§4.5: Enviando Moedas com Transações Brutas Automatizadas](04_5_Sending_Coins_with_Automated_Raw_Transactions.md), o Bitcoin calculará as taxas de transação para nós. Isso é feito usando taxas flutuantes, onde o ```bitcoind``` observa quanto tempo as transações estão demorando para confirmar e calcula automaticamente o que devemos gastar.
Podemos ter um controle dessas informações colocando os valores racionais no nosso arquivo ```~/.bitcoin/bitcoin.conf```. Os valores de baixo custo a seguir garantiríam que houvesse uma taxa de transação mínima de 10.000 satoshis por kByte de dados em nossa transação e solicitaríam que as taxas flutuantes calculassem uma boa quantia para colocar a nossa transação nos próximos seis blocos.
```
mintxfee=0.0001
txconfirmtarget=6
```
No entanto, como iremos partir do pressuposto que ninguém que esteja fazendo este tutorial queira esperar para as transações serem confirmadas, vamos adotar os seguintes valores:
```
mintxfee=0.001
txconfirmtarget=1
```
Devemos inserí-los no arquivo ```~/.bitcoin/bitcoin.conf```, na seção principal, no início do arquivo ou se quisermos ter a certeza que nunca iremos utilizá-lo em outro lugar, podemos colocar na seção ```[test]```.
Para trabalharmos neste tutorial, estamos dispostos a gastar 100.000 satoshis por kB em cada transação, e queremos colocar cada transação no próximo bloco! Para colocar isso em uma perspectiva para melhor entendimento, uma transação simples é executada com um tamanho de 0,25 KB a 1 KB, então estaremos pagando algo em torno de 25 mil a 100 mil satoshis, sendo que atualmente, taxas acima de 10 mil são consideradas altíssimas para transações de quantidade média.
Depois de editar o arquivo ```bitcoin.conf```, vamos reiniciar o bitcoind usando dois comandos:
```
$ bitcoin-cli stop
$ bitcoind -daemon
```
## Obtendo um Endereço
Precisamos encontrar algum endereço para qual enviar nossas moedas. Normalmente, alguém nos envia um endereço e talvez nos dê uma assinatura para provar que é o proprietário desse endereço. Como alternativa, podemos fornecer um QR code para que possamos digitalizar, evitando assim possíveis erros de digitação na hora de colocar o endereço no local do destinatário. Em nosso caso, vamos enviar os bitcoins para `n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi`, que é o endereço de retorno de um antigo faucet da rede Testenet.
> :book: ***O que é um QR code?*** Um QR code é apenas um jeito diferente de passar o endereço Bitcoin. Muitas carteiras geram os QR codes para nós, enquanto alguns sites tentam convertê-los em um endereço usando o QR code. Obviamente, só podemos aceitar um QR code de um site no qual confiamos. Um pagador pode usar um leitor de código de barras para ler o código QR e, em seguida, pagá-lo.
## Enviando os Bitcoins
Agora estamos prontos para enviar alguns bitcoins. Na verdade, isso é bastante simples por meio da linha de comando. Basta usar ```bitcoin-cli sendtoaddress [endereço] [quantidade]```. Portanto, para enviar uns satoshinhos para o endereço `n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi`, basta fazer o seguinte:
```
$ txid=$(bitcoin-cli sendtoaddress n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi 0.001)
$ echo $txid
93250d0cacb0361b8e21030ac65bc4c2159a53de1075425d800b2d7a8ab13ba8
```
> 🙏 Para ajudar a manter os faucets da rede de testes vivos, tente usar o endereço que nos foi enviado os bitcoins no capítulo anterior, onde falamos sobre os recebimentos de transações.
Precisamos nos certificar de que o endereço digitado é o lugar para onde desejamos enviá-lo. Por isso, certifique-se _duas vezes_. Se cometermos algum erro no Bitcoin, não há como voltar atrás.
Iremos receber um txid de retorno quando usarmos este comando.
> ❕ Você pode acabar com um código de erro se não tivermos bitcoins suficientes na carteira para fazer a transação. Dependendo do nosso saldo atual, que podemos acessar usando o ```bitcoin-cli getbalance```, pode ser necessário ajustar o valor que iremos enviar para que bata com o valor que está sendo enviado, não se esquecendo da taxa de transação no meio deste processo. Se o nosso saldo atual for 0,001, podemos tentar enviar 0,0001. Como alternativa, seria melhor tirar a taxa que esperamos pagar que foi enviada na mensagem de erro do nosso saldo atual. Esta é uma boa prática, pois muitas carteiras esperam que calculemos nosso próprio valor + taxas ao fazermos as transações, mesmo dentre as corretoras mais populares.
> :warning: **ATENÇÃO:** O comando ```bitcoin-cli``` realmente gera comandos usando o JSON-RPC quando está se comunicando com o bitcoind. Eles podem ser muito exigentes. Este é um exemplo: Se listarmos a quantidade de bitcoin sem o zero à esquerda (ou seja usando ".1" em vez de "0.1"), o ```bitcoin-cli``` irá acusar um erro com uma mensagem misteriosa.
> :warning: **ATENÇÃO:** Mesmo se formos cuidadosos com nossos dados, é possível que haja este erro: _"Fee estimation failed. Fallbackfee is disabled"_. De maneira geral, isso significa que nosso ```bitcoind``` local não tem informações suficientes para estimar as taxas. Não é para vermos isso se tivermos esperado que nossa blockchain sincronize e configure nosso sistema com o Bitcoin Standup. Mas se não estivermos totalmente sincronizados, podemos nos deparar com este erro. Também pode ser que não estejamos usando um ```bitcoin.conf``` padrão: A informação ```blocksonly = 1``` fará com que nosso ```bitcoind``` não consiga estimar as taxas.
## Examinando Nossa Transação
Podemos ver nossa transação usando o ID de transação:
```
{
"amount": -0.00100000,
"fee": -0.00022200,
"confirmations": 0,
"trusted": true,
"txid": "93250d0cacb0361b8e21030ac65bc4c2159a53de1075425d800b2d7a8ab13ba8",
"walletconflicts": [
],
"time": 1592604194,
"timereceived": 1592604194,
"bip125-replaceable": "no",
"details": [
{
"address": "n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi",
"category": "send",
"amount": -0.00100000,
"vout": 1,
"fee": -0.00022200,
"abandoned": false
}
],
"hex": "0200000001e982921bb0189afc486e20bb05cc5825c71a0ba8868043ed04ece9ab0cb12a8e010000006a47304402200fc493a01c5c9d9574f7c321cee6880f7f1df847be71039e2d996f7f75c17b3d02203057f5baa48745ba7ab5f1d4eed11585bd8beab838b1ca03a4138516fe52b3b8012102fd5740996d853ea51a6904cf03257fc11204b0179f344c49739ec5b20b39c9bafeffffff02e8640d0000000000160014d37b6ae4a917bcc873f6395741155f565e2dc7c4a0860100000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac780b1b00"
}
```
Você pode ver não apenas o valor transferido (0,001 BTC), mas também uma taxa de transação (0,000222 BTC), que é cerca de um quarto da taxa mínima de 0,001 BTC/kB que foi definida, o que sugere que a transação foi de cerca de um quarto de kB de tamanho.
Enquanto esperamos que ela seja confirmada, podemos notar que o ```bitcoin-cli getbalance``` mostra que nosso dinheiro já foi debitado. Da mesma forma, o ```bitcoin-cli listunspent``` mostrará que uma transação inteira foi perdida, mesmo que fosse mais do que o que queríamos enviar. Há uma razão para isso: Sempre que temos moedas entrando, precisamos enviar _tudo_ junto, e temos que fazer um pouco de malabarismos se quisermos realmente ficar com parte dele! Mais uma vez, o ```sendtoaddress``` cuida de tudo isso para nós, o que significa que não precisamos nos preocupar em fazer qualquer alteração até enviar uma transação bruta. Nesse caso, uma nova transação aparecerá com nossa alteração quando nosso envio for incorporado a um bloco.
## Resumo: Enviando Moedas da Maneira Fácil
Para enviar moedas facilmente, precisamos nos certificar de que nossos padrões de transação sejam racionais, obtendo um endereço e enviando as nossas moedas para lá. É por isso que esse modo é o mais fácil deles!
> :fire: ***Qual é o poder de enviar moedas da maneira fácil?***
> _As vantagens._ É fácil. Não precisamos nos preocupar com coisas misteriosas como UTXOs. Não precisamos calcular as taxas de transação manualmente, então, é provável que não iremos cometer erros que custem grandes valores. Se o nosso único objetivo é sentar na frente do computador e enviar alguns bitcoins, este é o caminho certo para fazer isso.
> _As desvantagens._ É alto nível. Temos muito pouco controle sobre o que está acontecendo e não podemos fazer nada demais. Se estamos planejando desenvolver um software mais complexo utilizando o Bitcoin ou se desejamos um entendimento mais profundo de como o Bitcoin funciona, então a maneira fácil é apenas um carrossel sem graça antes de chegarmos nas montanhas russas.
## O Que Vem Depois?
Vamos continuar "Enviando Transações no Bitcoin" na sessão [§4.2 Criando Uma Transação Bruta](04_2_Creating_a_Raw_Transaction.md).

View File

@ -0,0 +1,273 @@
# 4.2 Criando uma Transação Bruta
Agora estamos prontos para criar transações brutas no Bitcoin. Isso permite que enviemos dinheiro, mas que criemos as transações com a precisão desejada. Nesta primeira seção, iremos nos concentrar em uma transação simples de uma entrada e uma saída. Este tipo de transação _não_ é realmente útil, porque raramente vamos querer enviar todo o nosso dinheiro para uma pessoa (a menos que estejamos apenas encaminhando, como se estivesse movendo coisas de uma carteira para outra). Portanto, esse _não é o melhor método_ para enviar dinheiro. É apenas um conteúdo fundamental para _realmente_ enviar dinheiro com uma transação bruta.
## Compreendendo a Transação no Bitcoin
Antes de mergulhar na criação de transações brutas, devemos nos certificar de que entendemos como uma transação no Bitcoin funciona. Tudo gira entorno dos UTXOs.
> :book: ***O que é um UTXO?*** Quando recebemos dinheiro em nossa carteira Bitcoin, ele aparece como uma transação individual. Cada uma dessas transações é chamada de "Saída de Transação Não-Gasta" (Unspent Transaction Output em inglês, mais conhecido como UTXO). Não importa se vários pagamentos foram feitos para o mesmo endereço ou para vários endereços: cada transação recebida permanece distinta na carteira como um UTXO.
Ao criarmos uma nova transação de saída, reunimos um ou mais UTXOs, cada um representando um pouquinho do dinheiro que recebemos. Nós os usamos como entradas para uma nova transação. Juntos, o valor deles deve ser igual ao que desejamos gastar _ou mais do que o total_. Em seguida, geramos uma ou mais saídas, que dão o dinheiro representado pelas entradas a uma ou mais pessoas. Isso cria novos UTXOs para os destinatários, que podem então usá-los para financiar transações futuras.
Aqui está o truque: _Todos os UTXOs que coletarmos são gastos na íntegra!_ Isso significa que se quisermos enviar apenas parte do dinheiro em um UTXO para outra pessoa, também precisamos gerar uma saída adicional que envia o resto para nós! Por enquanto, não vamos nos preocupar com isso, mas o uso de um endereço de mudança será vital ao passar da teoria deste capítulo para transações mais práticas.
## Listando as Transações Não-Gastas
Para criar uma nova transação bruta, devemos saber quais UTXOs estão disponíveis para gastar. Podemos determinar essas informações com o comando ```bitcoin-cli listunspent```:
```
$ bitcoin-cli listunspent
[
{
"txid": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
"vout": 0,
"address": "mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
"label": "",
"scriptPubKey": "76a9141b72503639a13f190bf79acf6d76255d772360b788ac",
"amount": 0.00010000,
"confirmations": 20,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/1']02fd5740996d853ea51a6904cf03257fc11204b0179f344c49739ec5b20b39c9ba)#62rud39c",
"safe": true
},
{
"txid": "61f3b7016bf1ecc3987b8805207e79362e4de8026682e149107999b779426e3a",
"vout": 1,
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
"label": "",
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
"amount": 0.00050000,
"confirmations": 3,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
"safe": true
},
{
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
"vout": 0,
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
"label": "",
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
"amount": 0.00022000,
"confirmations": 3,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
"safe": true
}
]
```
Esta lista mostra três UTXOs diferentes, no valor de 0,0001, 0,0005 e 0,00022 BTC. Observe que cada um tem o próprio _txid_ distinto e permanece seperado na carteira, até mesmo os dois últimos, que foram enviados para o mesmo endereço.
Quando quisermos gastar um UTXO, não é suficiente apenas saber o id da transação. Isso porque cada transação pode ter várias saídas! Lembra daquele primeiro valor que o faucet nos enviou? Na transação, parte do dinheiro foi para nós e parte para outra pessoa. O ```txid``` se refere à transação geral, enquanto um ```vout``` diz qual das múltiplas saídas recebemos. Nesta lista, cada uma dessas transações é a primeira ```vout``` de uma transação anterior, mas _não necessariamente é sempre o caso_.
Portanto, o txid+vout=UTXO. Essa será a base de qualquer transação bruta.
## Escrevendo uma Transação Bruta Com Uma Saída
Agora estamos prontos para escrever um exemplo simples de transação bruta que mostra como enviar um UTXO inteiro para outra pessoa. Conforme falamos anteriormente, este não é um caso muito realista.
> :warning: **ATENÇÃO:** É muito fácil perder dinheiro com uma transação bruta. Considere que todas as instruções sobre como enviar bitcoins por meio de transações brutas são _muito_, _muito_ perigosas. Sempre que estiver enviando moedas na _mainnet_ para outras pessoas, devemos usar um dos outros métodos explicados neste capítulo. Criar transações brutas é extremamente útil se estivermos escrevendo programas para o bitcoin, mas _só_ neste caso. (Por exemplo: ao escrever este exemplo para uma versão anterior deste tutorial, acidentalmente gastamos a transação errada, embora tivéssemos cerca de 10 vezes mais. Quase tudo isso foi enviado para os mineradores.)
### Preparando a Transação Bruta
Para as melhores práticas, iremos começar cada transação registrando cuidadosamente os txids e vouts que iremos gastar.
Nesse caso, vamos gastar um no valor de 0,00050000 BTC porque é o único com um valor decente.
```
$ utxo_txid="61f3b7016bf1ecc3987b8805207e79362e4de8026682e149107999b779426e3a"
$ utxo_vout="1"
```
Da mesma forma, devemos registrar o endereço do destinatário para ter certeza de que está correto. No nosso exemplo estamos enviando novamente o saldo de volta para o faucet:
```
$ recipient="n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"
```
Como de prache, vamos verificar as variáveis com cuidado, para ter certeza de que são aquilo que esperamos!
```
$ echo $utxo_txid
61f3b7016bf1ecc3987b8805207e79362e4de8026682e149107999b779426e3a
$ echo $utxo_vout
1
$ echo $recipient
n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi
```
Esse destinatário é particularmente importante, porque se bagunçarmos tudo, nosso dinheiro terá dado _tchau tchau_! E como já vimos, escolher a transação errada pode resultar em perda de dinheiro! Portanto, vamos verificar tudo, pelo menos uma vez mais do que a quantidade de costume.
### Entendendo a Taxa de Transação
Cada transação tem uma taxa associada. Ela fica _implícita_ quando enviamos uma transação bruta: O valor que vamos pagar como taxa é sempre igual ao valor de entrada menos o valor de saída. Portanto, temos que diminuir um pouco o valor enviado para ter certeza de que nossa transação será realizada.
> :warning: **ATENÇÃO:** Esta é a parte muito perigosa das transações brutas!! Como gastamos automaticamente toda a quantidade de UTXOs que tivermos, é extremamente importante certificar-se de que sabemos: (1) precisamente quais UTXOs estamos utilizando; (2) exatamente quanto dinheiro ele possui; (3) exatamente quanto dinheiro estamos enviando; e (4) qual é a diferença que ficará para os mineradores. Se errarmos e, por exemplo, usarmos o UTXO errado (um que tenha mais dinheiro do que pensávamos) ou se enviarmos muito pouco dinheiro, o excesso será perdido. _Para sempre_! Não podemos cometer esse erro! Por isso, é importante sabermos as entradas e saídas com _precisão_. Ou melhor, não utilizarmos as transações brutas, exceto como parte de um programa cuidadosamente considerado e verificado três vezes.
> :book: ***Quanto devemos gastar com taxas de transação?*** [Bitcoin Fees](https://bitcoinfees.21.co/) tem uma ótima avaliação ao vivo. O site diz que "fastest and cheapest transaction fee is currently XXX satoshis/byte" onde o XXX será a quantidade de satoshis por byte que precisaremos pagar e também, "For the median transaction size of YYY bytes, this results in a fee of ZZ,ZZZ satoshis", onde YYY é o tamanho de uma transação média e ZZ,ZZZ é o resultado da multiplicação entre YYY e XXX. No caso, precisamos apenas observar o valor ZZ,ZZZ descrito no site.
No momento em que este tutorial está sendo escrito, o _Bitcoin Fees_ sugere uma taxa de transação de cerca de 10.000 satoshis, que é o mesmo que 0,0001 BTC. Obviamente, isso é para a mainnet, não para a testnet, mas queremos testar as coisas de forma realista, então iremos utilizar esta quantidade.
Nesse caso, isso significa que vamos pegar 0,0005 BTC no UTXO que selecionamos, reduzindo a quantidade de 0,0001 BTC para a taxa de transação e enviar os 0,0004 BTC restantes. (E este é um exemplo do porque os micropagamentos não funcionam na rede principal do Bitcoin, porque uma taxa de transação que consome 20% do valor enviado é muito cara, agora imagina se os valores forem menores do que a taxa de transação. Mas é por isso que temos a Lightning.)
> :warning: **ATENÇÃO:** Quanto menor for a taxa de transação, mais tempo irá demorar para que nossa transação entre na blockchain. O site _Bitcoin Fees_ lista os tempos que precisaremos esperar em relação a quantidade de satoshi por byte. Como os blocos são construídos em média a cada 10 minutos, a mudança de taxa pode significar uma mudança de espera de minutos para algumas horas ou dias! Portanto, escolha uma taxa de transação apropriada para o que estamos enviando. É importante observar que nunca devemos colocar taxas abaixo da quantidade mínima para transação, que é 0,0001 BTC.
### Escrevendo a Transação Bruta
Agora estamos prontos para criar a transação bruta. Usaremos o comando ```createrawtransaction```, que pode parecer um pouco intimidante. Isso porque o comando ```createrawtransaction``` não o protege inteiramente do JSON RPC que o ```bitcoin-cli``` utiliza. Ao invés disso, vamos inserir uma matriz JSON para listar os UTXOs que está gastando e um objeto JSON para listar as saídas.
Este é o formato padrão:
```
$ bitcoin-cli createrawtransaction
'''[
{
"txid": "'$your_txid'",
"vout": '$your_vout'
}
]'''
'''{
"'$your_recipient'": bitcoin_amount
}'''
```
Não, não é um erro de digitação. Existem todos os tipos de citações malucas, mas confie que elas farão a coisa certa. Vamos usar `'''` para marcar o início e o fim do array e no objeto JSON. Protegendo as palavras normais como ```"this"```, mas não precisamos proteger os números: ```0```. Se forem variáveis, vamos inserir as aspas simples, como ```"'$this_word'"``` e ```'$this_num'```. (Ufa! Não se preocupe, você pega o jeito).
Aqui está um comando que cria uma transação bruta para enviar $utxo para o $recipient.
```
$ rawtxhex=$(bitcoin-cli createrawtransaction '''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' '''{ "'$recipient'": 0.0004 }''')
$ echo $rawtxhex
02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f3610100000000ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000
```
### Verificando a Transação Bruta
Depois disso, devemos verificar a transação bruta com o comando ```decoderawtransaction``` para ter certeza de que faremos a coisa certa.
```
$ bitcoin-cli decoderawtransaction $rawtxhex
{
"txid": "dcd2d8f0ec5581b806a1fbe00325e1680c4da67033761b478a26895380cc1298",
"hash": "dcd2d8f0ec5581b806a1fbe00325e1680c4da67033761b478a26895380cc1298",
"version": 2,
"size": 85,
"vsize": 85,
"weight": 340,
"locktime": 0,
"vin": [
{
"txid": "61f3b7016bf1ecc3987b8805207e79362e4de8026682e149107999b779426e3a",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00040000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 e7c1345fc8f87c68170b3aa798a956c2fe6a9eff OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"
]
}
}
]
}
```
É importante verificarmos o ```vin```. Estamos gastando a transação certa? Ela contém a quantia de dinheiro esperada? (Vamos verificar com o comando ```bitcoin-cli gettransaction``` e nos certificar de olhar o ```vout``` se está correto). Além disso, vamos verificar o nosso ```vout```. Estamos enviando a quantidade correta? Está indo para o endereço certo? Finalmente, vamos fazer as contas para ter certeza de que o dinheiro que irá para as taxas está correto. O valor do UTXO menos a quantia que está sendo gasta é igual à taxa da transação esperada?
> :information_source: **NOTA:** Podemos notar que cada entrada tem um número de sequência, definido aqui como 4294967295, que é 0xFFFFFFFF. Esta é a última fronteira das transações Bitcoin, porque é um campo padrão em transações que foram originalmente planejadas para um propósito específico, mas nunca foram totalmente implementadas. Portanto, agora existe esse inteiro parado em transações que podem ser reaproveitadas para outros usos. E, de fato, tem sido. No momento em que este livro foi escrito, havia três usos diferentes para a variável chamada ```nSequence``` no código Bitcoin Core: Ela habilita a possibilidade de RBF, ```nLockTime``` e timelocks relativos. Se não houver nada de estranho acontecendo, o ```nSequence``` será definido como 4294967295. Ajustar para um valor mais baixo sinaliza que coisas especiais estão acontecendo.
### Assinando a Transação Bruta
Até o momento, nossa transação bruta é apenas uma teoria: _Podemos_ enviá-la, mas nada irá acontecer. Precisamos fazer algumas coisas para colocá-la na rede.
Primeiro, precisamos assinar nossa transação bruta:
```
$ bitcoin-cli signrawtransactionwithwallet $rawtxhex
{
"hex": "02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f361010000006a4730440220335d15a2a2ca3ce6a302ce041686739d4a38eb0599a5ea08305de71965268d05022015f77a33cf7d613015b2aba5beb03088033625505ad5d4d0624defdbea22262b01210278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000",
"complete": true
}
$ signedtx="02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f361010000006a4730440220335d15a2a2ca3ce6a302ce041686739d4a38eb0599a5ea08305de71965268d05022015f77a33cf7d613015b2aba5beb03088033625505ad5d4d0624defdbea22262b01210278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000"
```
Observe que capturamos o hexadecimal assinado manualmente, ao invés de tentar analisá-lo a partir do objeto JSON. Um pacote de software chamado "JQ" poderia ter um desempenho melhor, como explicaremos no próximo prefácio.
### Enviando a Transação Bruta
Agora temos uma transação bruta pronta para ser usada, mas nada acontece com ela se não a colocarmos na rede, o que iremos fazer com o comando ```sendrawtransaction```. O retorno dele será uma txid:
```
$ bitcoin-cli sendrawtransaction $signedtx
a1fd550d1de727eccde6108c90d4ffec11ed83691e96e119d842b3f390e2f19a
```
Iremos observar imediatamente que o UTXO e o as nossas moedas foram removidas da nossa carteira:
```
$ bitcoin-cli listunspent
[
{
"txid": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
"vout": 0,
"address": "mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
"label": "",
"scriptPubKey": "76a9141b72503639a13f190bf79acf6d76255d772360b788ac",
"amount": 0.00010000,
"confirmations": 23,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/1']02fd5740996d853ea51a6904cf03257fc11204b0179f344c49739ec5b20b39c9ba)#62rud39c",
"safe": true
},
{
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
"vout": 0,
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
"label": "",
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
"amount": 0.00022000,
"confirmations": 6,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
"safe": true
}
]
$ bitcoin-cli getbalance
0.00032000
```
Logo o ```listtransactions``` deve mostrar uma transação confirmada da categoria 'send'.
```
{
"address": "n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi",
"category": "send",
"amount": -0.00040000,
"vout": 0,
"fee": -0.00010000,
"confirmations": 1,
"trusted": true,
"txid": "a1fd550d1de727eccde6108c90d4ffec11ed83691e96e119d842b3f390e2f19a",
"walletconflicts": [
],
"time": 1592608574,
"timereceived": 1592608574,
"bip125-replaceable": "no",
"abandoned": false
}
```
Podemos observar que ele corresponde aos endereços ```txid``` e ```recipient``` (recebedor). Não só mostra o ```amount``` (montante) enviado, mas também mostra a ```fee``` (taxa) da transação. E, a transação já recebeu uma confirmação, porque oferecemos uma taxa que a faria ser colocada em um bloco rapidamente.
Parabéns! Estamos um pouco mais pobres agora!
## Resumo: Criando uma Transação Bruta
Quando satoshinhos entram na nossa carteira Bitcoin, eles permanecem em quantidades distintas, chamadas de UTXOs. Ao criar uma transação bruta para enviar as moedas, usamos um ou mais UTXOs para financiá-la. Podemos então, criar uma transação bruta, assiná-la e enviá-la pela rede Bitcoin. No entanto, esta é apenas uma base do que realmente acontece: geralmente precisaremos criar uma transação bruta com várias saídas para realmente enviar algo na rede Bitcoin!
## O Que Vem Depois?
Vamos fazer uma pausa em "Enviando Transações no Bitcoin" para lermos o [Prefácio: Usando JQ](04_2__Interlude_Using_JQ.md).

View File

@ -0,0 +1,429 @@
# Prefácio: Usando JQ
A criação de uma transação bruta revelou como resultados mais complexos do ```bitcoin-cli``` não podem ser salvos facilmente em variáveis de linha de comando. A resposta para isso é usar o JQ, que permite filtrar elementos individuais de dados JSON mais complexos.
## Instalando JQ
O JQ está disponível em um [repositório no Github](https://stedolan.github.io/jq/). Basta fazermos o download para Linux, OS X ou Windows, de acordo com o seu sistema operacional.
Depois de baixar o binário, podemos instalá-lo em nosso sistema. Se estivermos trabalhando em um VPS Debian, fazendo o passo a passo desse curso, nossa instalação será parecida com esta:
```
$ mv jq-linux64 jq
$ sudo /usr/bin/install -m 0755 -o root -g root -t /usr/local/bin jq
```
> :book: ***O que é JQ?*** O repositório explica melhor, dizendo "O jq é como o sed para dados JSON - você pode usá-lo para dividir, filtrar, mapear e transformar dados estruturados com a mesma facilidade que o sed, awk, e grep permitem que você brinque com o texto".
## Usando JQ Para Acessar o Valor de um Objeto JSON Pelo Índice
**Caso de Uso:** _Capturando o hex de uma transação bruta assinada._
Na seção anterior, o uso de ```signrawtransaction``` não pareceu ser um bom método devido ao fato de não ser capaz de capturar os dados facilmente em variáveis devido a seu retorno no formato JSON:
```
$ bitcoin-cli signrawtransactionwithwallet $rawtxhex
{
"hex": "02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f361010000006a4730440220335d15a2a2ca3ce6a302ce041686739d4a38eb0599a5ea08305de71965268d05022015f77a33cf7d613015b2aba5beb03088033625505ad5d4d0624defdbea22262b01210278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000",
"complete": true
}
```
Felizmente, o JQ pode facilmente capturar os dados desse tipo!
Para usar o JQ, vamos executar ```jq``` no backend de um pipe e sempre usar a invocação padrão que é ```jq -r '.'```. O ```-r``` diz ao JQ para produzir uma saída bruta, que funcionará para variáveis de linha de comando, enquanto o ```.``` diz ao JQ para mostrar na tela. Protegemos esse argumento com ```' '``` porque precisaremos dessa proteção mais tarde conforme nossas invocações ```jq``` se tornarem mais complexas.
Para capturar um valor específico de um objeto JSON, basta listar o índice após o ```.```:
```
$ bitcoin-cli signrawtransactionwithwallet $rawtxhex | jq -r '.hex'
02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f361010000006a4730440220335d15a2a2ca3ce6a302ce041686739d4a38eb0599a5ea08305de71965268d05022015f77a33cf7d613015b2aba5beb03088033625505ad5d4d0624defdbea22262b01210278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000
```
Com essa ferramenta em mãos, podemos capturar as informações de objetos JSON para variáveis na linha de comando:
```
$ signedtx=$(bitcoin-cli signrawtransactionwithwallet $rawtxhex | jq -r '.hex')
$ echo $signedtx
02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f361010000006a4730440220335d15a2a2ca3ce6a302ce041686739d4a38eb0599a5ea08305de71965268d05022015f77a33cf7d613015b2aba5beb03088033625505ad5d4d0624defdbea22262b01210278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000
```
Podemos usar então essas variáveis facilmente e sem erros:
```
$ bitcoin-cli sendrawtransaction $signedtx
3f9ccb6e16663e66dc119de1866610cc4f7a83079bfec2abf0598ed3adf10a78
```
## Usando JQ Para Acessar Valores Únicos de um Objeto JSON em um Array Pelo Índice
**Caso de Uso:** _Capturando o txid e o vout para um UTXO selecionado._
Extrair dados de um objeto JSON é fácil, mas e se esse objeto JSON estiver em um array JSON? O comando ```listunspent``` oferece um ótimo exemplo, porque geralmente contém várias transações diferentes. E se quisermos capturar as informações específicas de _um_ deles?
Ao trabalhar com um array JSON, a primeira coisa que precisamos fazer é informar ao JQ qual índice acessar. Por exemplo, podemos estar olhando nosswas transações no ```listunspent``` e decidimos que queremos trabalhar com a segunda. Podemos usar o ```'. [1]'``` para acessar o primeiro elemento. O ```[]``` diz que estamos referenciando um array JSON e o ```0``` diz que queremos o índice 0.
```
$ bitcoin-cli listunspent | jq -r '.[1]'
{
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
"vout": 0,
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
"label": "",
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
"amount": 0.00022,
"confirmations": 9,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
"safe": true
}
```
Podemos então capturar um valor individual desse array selecionado (1) usando um pipe _dentro_ dos argumentos JQ; e então (2) solicitando o valor específico posteriormente, como no exemplo anterior. Isso iria capturar o ```txid``` do primeiro objeto JSON no array JSON produzido pelo comando ```listunspent```:
```
$ bitcoin-cli listunspent | jq -r '.[1] | .txid'
91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c
```
Observe cuidadosamente como os ```' '``` circundam toda a expressão JQ _incluindo_ o pipe.
Este método pode ser usado para preencher variáveis para um UTXO que desejamos utilizar:
```
$ newtxid=$(bitcoin-cli listunspent | jq -r '.[1] | .txid')
$ newvout=$(bitcoin-cli listunspent | jq -r '.[1] | .vout')
$ echo $newtxid
91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c
$ echo $newvout
0
```
Pronto! Agora podemos criar uma nova transação bruta usando nosso primeiro UTXO como entrada, sem ter que digitar qualquer uma das informações do UTXO manualmente!
## Usando JQ Para Acessar Valores de Objetos JSON Correspondentes em um Array Por Índices
**Caso de Uso:** _Listar o valor de todos os UTXOs._
Ao invés de acessar um único valor específico em um objeto JSON específico, podemos acessar todos os valores específicos em todos os objetos JSON. Isso é feito com ```.[]```, Onde nenhum índice é especificado. Por exemplo, podemos listar todos os saldos não gastos:
```
$ bitcoin-cli listunspent | jq -r '.[] | .amount'
0.0001
0.00022
```
## Usando JQ Para Cálculos Simples Por Índices
**Caso de Uso:** _Adicionando o valor de todos os UTXOs não gastos._
Neste ponto, podemos começar a usar o retorno do JQ para fazermos uma matemática simples. Por exemplo, somar os valores dessas transações não gastas com um script ```awk``` simples nos daria o equivalente ao ```getbalance```:
```
$ bitcoin-cli listunspent | jq -r '.[] | .amount' | awk '{s+=$1} END {print s}'
0.00032
$ bitcoin-cli getbalance
0.00032000
```
## Usando JQ Para Exibir Vários Valores de um Objeto JSON em um Array Por Vários Índices
**Caso de Uso:** _Listar as informações de uso para todos os UTXOs._
O JQ pode capturar facilmente elementos individuais de objetos JSON e arrays e colocar os elementos em variáveis. Esse será o principal uso que iremos fazer nas seções futuras. No entanto, ele também pode ser usado para reduzir grandes quantidades de informações geradas pelo ```bitcoin-cli``` em quantidades razoáveis de informações.
Por exemplo, podemos querer ver uma lista de todos os nossos UTXOs (```.[]```) E obter uma lista de todas as informações mais importantes (```.txid, .vout, .amount```):
```
$ bitcoin-cli listunspent | jq -r '.[] | .txid, .vout, .amount'
ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36
0
0.0001
91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c
0
0.00022
```
Isso torna mais fácil decidir quais UTXOs gastar em uma transação bruta, mas não é muito bonito.
Felizmente, o JQ também permite que sejamos mais sofisticados. Podemos usar as ```{}``` para criar novos objetos JSON (para análise adicional ou para um retorno mais bonito). Também podemos definir o nome do novo índice para cada um dos valores. A saída resultante deve ser muito mais intuitiva e menos sujeita a erros (embora, menos útil para jogar as informações diretamente nas variáveis).
O exemplo a seguir mostra exatamente a mesma análise do ```listunspent```, mas com cada objeto JSON antigo reconstruído como um novo objeto JSON abreviado, com todos os novos valores nomeados com os índices antigos:
```
$ bitcoin-cli listunspent | jq -r '.[] | { txid: .txid, vout: .vout, amount: .amount }'
{
"txid": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
"vout": 0,
"amount": 0.0001
}
{
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
"vout": 0,
"amount": 0.00022
}
```
Podemos, é claro, renomear nossos novos índices conforme acharmos necessário. Não há nada de mágico nos nomes originais:
```
$ bitcoin-cli listunspent | jq -r '.[] | { tx: .txid, output: .vout, bitcoins: .amount }'
{
"tx": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
"output": 0,
"bitcoins": 0.0001
}
{
"tx": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
"output": 0,
"bitcoins": 0.00022
}
```
## Usando JQ Para Acessar Objetos JSON Por Valor Pesquisado
**Caso de Uso:** _Pesquisando automaticamente os UTXOs que estão sendo usados em uma transação._
As pesquisas JQ até agora têm sido bastante simples: Usamos um índice para pesquisar um ou mais valores em um objeto JSON ou no array. Mas e se quisermos pesquisar um valor em um objeto JSON... usando outro valor? Esse tipo de pesquisa indireta tem aplicabilidade real quando estamos trabalhando com transações criadas usando os UTXOs existentes. Por exemplo, podemos calcular o valor da soma dos UTXOs sendo usados em uma transação, algo de vital importância.
Este exemplo usa a seguinte transação bruta. Podemos observar que esta é uma transação bruta mais complexa com duas entradas e duas saídas. Aprenderemos como fazer isso nas próximas seções, mas por enquanto, é necessário sermos capazes de oferecer exemplos robustos. Observe que, ao contrário dos nossos exemplos anteriores, neste, temos dois objetos em nosso array ```vin``` e dois em nosso array ```vout```.
```
$ bitcoin-cli decoderawtransaction $rawtxhex
{
"txid": "6f83a0b78c598de01915554688592da1d7a3047eacacc8a9be39f5396bf0a07e",
"hash": "6f83a0b78c598de01915554688592da1d7a3047eacacc8a9be39f5396bf0a07e",
"size": 160,
"vsize": 160,
"version": 2,
"locktime": 0,
"vin": [
{
"txid": "d261b9494eb29084f668e1abd75d331fc2d6525dd206b2f5236753b5448ca12c",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
},
{
"txid": "c7c7f6371ec19330527325908a544bbf8401191645598301d24b54d37e209e7b",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 1.00000000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 cfc39be7ea3337c450a0c77a839ad0e160739058 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914cfc39be7ea3337c450a0c77a839ad0e16073905888ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"mzTWVv2QSgBNqXx7RC56zEhaQPve8C8VS9"
]
}
},
{
"value": 0.04500000,
"n": 1,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 166692bda9f25ced145267bb44286e8ee3963d26 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914166692bda9f25ced145267bb44286e8ee3963d2688ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"mhZQ3Bih6wi7jP1tpFZrCcyr4NsfCapiZP"
]
}
}
]
}
```
### Recuperando Valor(es)
Suponha que saibamos exatamente como essa transação é construída: sabemos que ela usa dois UTXOs como entrada. Para recuperar o txid para os dois UTXOs, poderíamos usar ```jq``` para consultar o valor .vin da transação e, em seguida, fazer referência ao primeiro índice do .vin e, então, ao valor .txid deste array. Posteriormente, poderíamos fazer o mesmo com o primeiro array e, em seguida, o mesmo com os dois valores .vout de .vin. Fácil:
```
$ usedtxid1=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[0] | .txid')
$ echo $usedtxid1
d261b9494eb29084f668e1abd75d331fc2d6525dd206b2f5236753b5448ca12c
$ usedtxid2=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[1] | .txid')
$ echo $usedtxid2
c7c7f6371ec19330527325908a544bbf8401191645598301d24b54d37e209e7b
$ usedvout1=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[0] | .vout')
$ echo $usedvout1
1
$ usedvout2=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[1] | .vout')
$ echo $usedvout2
1
```
No entanto, seria melhor ter um caso geral que salvasse _automaticamente_ todos os txids de nossos UTXOs.
Já sabemos que podemos acessar todos os ```.txid``` usando um valor do array ```.[] ```. Podemos usar isso para criar uma pesquisa geral no .txid:
```
$ usedtxid=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .txid'))
$ echo ${usedtxid[0]}
d261b9494eb29084f668e1abd75d331fc2d6525dd206b2f5236753b5448ca12c
$ echo ${usedtxid[1]}
c7c7f6371ec19330527325908a544bbf8401191645598301d24b54d37e209e7b
$ usedvout=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .vout'))
$ echo ${usedvout[0]}
1
$ echo ${usedvout[1]}
1
```
O único truque real aqui é como salvamos as informações usando o shell bash. Ao invés de salvar em uma variável com ```$(command)```, nós salvamos em um array com ```($(command))```. Fomos então capazes de acessar os elementos individuais do array bash com uma construção ```${variable [n]}```. Ao invés disso, poderíamos acessar todo o array usando a ```${variable [@]}```. (E antes que diga algo, ninguém nunca disse que o bash ficaria bonito).
> :warning: **ATENÇÃO:** Lembre-se sempre de que um UTXO é uma transação _mais_ um vout. Perdemos o vout na primeira vez que escrevemos este exemplo JQ, e ele parou de funcionar quando acabamos com uma situação em que dois ```vouts``` foram enviados da mesma transação.
### Recuperando o(s) Objeto(s) Relacionado(s)
Agora podemos usar as informações salvas no ```txid``` e no ```vout``` para referenciar os UTXOs no ```listunspent```. Para encontrar as informações sobre os UTXOs usados pela transação bruta, precisamos examinar todo o array JSON (```[]```) com as transações não-gastas. Podemos então escolher (```select```) objetos JSON individuais que incluam (```contains```) os txids. _Então_ selecionamos (```select```) as transações entre aquelas que _também_ contêm (```contain```) o valor correto.
O uso de outro nível do pipe é a metodologia padrão do JQ: Pegamos um conjunto de dados, depois a reduzimos para todas as transações relevantes e, em seguida, reduzimos para os valores que foram realmente usados nessas transações. No entanto, os argumentos ```select``` e ```contains``` são algo novo. Eles mostram um pouco da complexidade do JSON que vai além do escopo deste tutorial. Por enquanto, saiba apenas que esta invocação em particular funcionará para capturar objetos correspondentes.
Para começar de forma simples, vamos selecionar os dois UTXOs, um de cada vez:
```
$ bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${usedtxid[0]}'")) | select(.vout | contains('${usedvout[0]}'))'
{
"txid": "d261b9494eb29084f668e1abd75d331fc2d6525dd206b2f5236753b5448ca12c",
"vout": 1,
"address": "miSrC3FvkPPZgqqvCiQycq7io7wTSVsAFH",
"scriptPubKey": "76a91420219e4f3c6bc0f6524d538009e980091b3613e888ac",
"amount": 0.9,
"confirmations": 6,
"spendable": true,
"solvable": true
}
$ bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${usedtxid[1]}'")) | select(.vout | contains('${usedvout[1]}'))'
{
"txid": "c7c7f6371ec19330527325908a544bbf8401191645598301d24b54d37e209e7b",
"vout": 1,
"address": "mzizSuAy8aL1ytFijds7pm4MuDPx5aYH5Q",
"scriptPubKey": "76a914d2b12da30320e81f2dfa416c5d9499d08f778f9888ac",
"amount": 0.4,
"confirmations": 5,
"spendable": true,
"solvable": true
}
```
Ao invés disso, um simples bash usando um loop ```for``` poderia nos dar _todos_ os nossos UTXOs:
```
$ for ((i=0; i<${#usedtxid[*]}; i++)); do txid=${usedtxid[i]}; vout=${usedvout[i]}; bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${txid}'")) | select(.vout | contains('$vout'))'; done;
{
"txid": "d261b9494eb29084f668e1abd75d331fc2d6525dd206b2f5236753b5448ca12c",
"vout": 1,
"address": "miSrC3FvkPPZgqqvCiQycq7io7wTSVsAFH",
"scriptPubKey": "76a91420219e4f3c6bc0f6524d538009e980091b3613e888ac",
"amount": 0.9,
"confirmations": 7,
"spendable": true,
"solvable": true
}
{
"txid": "c7c7f6371ec19330527325908a544bbf8401191645598301d24b54d37e209e7b",
"vout": 1,
"address": "mzizSuAy8aL1ytFijds7pm4MuDPx5aYH5Q",
"scriptPubKey": "76a914d2b12da30320e81f2dfa416c5d9499d08f778f9888ac",
"amount": 0.4,
"confirmations": 6,
"spendable": true,
"solvable": true
}
```
Observe que estamos deixando um pouquinho mais feio nosso array ```${#usedtxid[*]}``` para determinar o tamanho dele e, em seguida, acessamos cada valor no array ```usedtxid``` e cada valor no array ```usedvout``` em paralelo, colocando-os em variáveis mais simples para termos um acesso menos feio.
## Usando JSON Para Cálculos Simples Por Valor
**Caso de Uso:** _Calcular automaticamente o valor dos UTXOs usados em uma transação._
Agora podemos ir um passo adiante e solicitar o .amount (ou qualquer outro par índice-valor do JSON) dos UTXOs que estamos recuperando.
Este exemplo repete o uso dos arrays ```$usedtxid``` e ```$usedvout``` definidos da seguinte forma:
```
$ usedtxid=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .txid'))
$ usedvout=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .vout'))
```
O mesmo script ```for``` pode ser usado para percorrer os arrays, mas com um pipe adicionado no JQ que produz o valor ```amount``` para cada um dos UTXOs selecionados.
```
$ for ((i=0; i<${#usedtxid[*]}; i++)); do txid=${usedtxid[i]}; vout=${usedvout[i]}; bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${txid}'")) | select(.vout | contains('$vout')) | .amount'; done;
0.9
0.4
```
Neste ponto, podemos somar os .amounts com um script ```awk```, para realmente ver quantas moedas estão nos UTXOs gastos na transação:
```
$ for ((i=0; i<${#usedtxid[*]}; i++)); do txid=${usedtxid[i]}; vout=${usedvout[i]}; bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${txid}'")) | select(.vout | contains('$vout')) | .amount'; done | awk '{s+=$1} END {print s}'
1.3
```
Ufa!
## Usando JQ Para Cálculos Complexos
**Caso de Uso:** _Calcular a taxa de uma transação._
Descobrir a taxa completa de transação neste ponto requer apenas mais um pouco de matemática: basta determinar quanto dinheiro está passando pelo .vout. Este é um uso simples de JQ onde apenas usamos o ```awk``` para somar o ```value``` de todas as informações do ```vout```:
```
$ bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vout [] | .value' | awk '{s+=$1} END {print s}'
1.045
```
Para completar o cálculo da taxa de transação, vamos subtrair o .vout .amount (1.045) do .vin .amount (1.3).
Para fazer isso, precisaremos instalar ```bc```:
```
$ sudo apt-get intall bc
```
Se juntarmos tudo, iremos criar uma calculadora completa com apenas um script de cinco linhas:
```
$ usedtxid=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .txid'))
$ usedvout=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .vout'))
$ btcin=$(for ((i=0; i<${#usedtxid[*]}; i++)); do txid=${usedtxid[i]}; vout=${usedvout[i]}; bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${txid}'")) | select(.vout | contains('$vout')) | .amount'; done | awk '{s+=$1} END {print s}')
$ btcout=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vout [] | .value' | awk '{s+=$1} END {print s}')
$ echo "$btcin-$btcout"| /usr/bin/bc
.255
```
E esse também é um bom exemplo de por que precisamos verificar nossas taxas: pretendíamos enviar uma taxa de transação com 5.000 satoshis, mas invés disso enviamos pagando 255.000 satoshis de taxa. Ops!
> :warning: **ATENÇÃO:** A primeira vez que escrevemos esta lição, realmente calculamos mal a nossa taxa e não a vimos até que executamos nossa calculadora de taxas. É *tão* fácil, que nosso dinheiro acabou. (O exemplo acima é, na verdade, de nossa segunda iteração da calculadora, e dessa vez cometemos o erro de propósito).
Para mais magia usando o JQ (e se alguma coisa não estiver clara), leia o [Manual JQ](https://stedolan.github.io/jq/manual/) e o [Livro de Receitas do JQ](https://github.com/stedolan/jq/wiki/Cookbook). Estaremos usando o JQ regularmente nos exemplos futuros.
## Fazendo Alguns Aliases Novos
Código em JQ pode ser um pouco pesado, então devemos considerar adicionar algumas invocações mais longas e interessantes ao nosso ```~/.bash_profile```.
Sempre que estivermos procurando por uma grande massa de informações em uma saída de objeto JSON por um comando ```bitcoin-cli```, precisamos considerar escrever um alias para reduzi-lo exatamente ao que desejamos observar.
```
alias btcunspent="bitcoin-cli listunspent | jq -r '.[] | { txid: .txid, vout: .vout, amount: .amount }'"
```
## Executando o Script de Taxa de Transação
O [Script de Cálculo de Taxa](../src/04_2_i_txfee-calc.sh) está disponível no diretório `src/`. Você pode baixá-lo e salvá-lo como ```txfee-calc.sh```.
> :warning: **ATENÇÃO:** Este script não foi verificado extensivamente. Se for usá-lo para verificar as taxas de transação reais, só deve fazê-lo depois de fazer uma verificação pessoal dos valores.
Certifique-se de que as permissões no script estejam corretas:
```
$ chmod 755 txfee-calc.sh
```
Podemos, então, executar o script da seguinte maneira:
```
$ ./txfee-calc.sh $rawtxhex
.255
```
Também podemos criar um alias:
```
alias btctxfee="~/txfee-calc.sh"
```
## Resumo: Usando JQ
O JQ facilita a extração de informações de arrays e objetos JSON. Ele também pode ser usado em scripts shell para cálculos bastante complexos que tornarão nossa vida mais fácil.
## O Que Vem Depois?
Continue "Enviando Transações no Bitcoin" na sessão [§4.3 Criando uma Transação Bruta com Argumentos Nomeados](04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md).

View File

@ -0,0 +1,97 @@
# 4.3 Criando uma Transação Bruta com Argumentos Nomeados
Às vezes, pode ser assustador descobrir a ordem correta dos argumentos para um comando ```bitcoin-cli```. Felizmente, podemos usar _argumentos nomeados_ como alternativa.
> :warning: **AVISO DE VERSÃO:** Esta é uma inovação do Bitcoin Core v0.14.0. Se usarmos os scripts de configuração do tutorial, o que é importante fazer, precisamos verificar novamente a versão se tiver algum problema. Há também um bug no uso do comando ```createrawtransaction``` usando argumentos nomeados que presumivelmente serão corrigidos na versão 0.14.1.
## Criando um Alias de Argumento Nomeado
Para usar um argumento nomeado, devemos executar o ```bitcoin-cli``` com o argumento ```-named```. Se planejamos fazer isso regularmente, provavelmente precisaremos criar um alias:
```
alias bitcoin-cli="bitcoin-cli -named"
```
Como de costume, isso é apenas para facilitar o uso, mas continuaremos usando todos os comandos para manter a clareza.
## Testando um Argumento Nomeado
Para saber quais são os nomes dos argumentos de um comando, precisamos consultar o ```bitcoin-cli help```. Ele listará os argumentos com a ordem adequada, mas agora também fornecerá nomes para cada um deles.
Por exemplo, `bitcoin-cli help getbalance` lista estes argumentos:
1. dummy [costumava ser account]
2. minconf
3. include_watchonly
4. avoid_reuse
O exemplo seguinte mostra um uso tradicional e não intuitivo do ```getbalance``` usando o argumento de confirmação mínimo:
```
$ bitcoin-cli getbalance "*" 1
```
Com argumentos nomeados, podemos esclarecer o que estamos fazendo, o que também minimiza os erros:
```
$ bitcoin-cli -named getbalance minconf=1
```
## Testando uma Transação Bruta
Veja como seriam os comandos para enviar uma transação bruta com argumentos nomeados:
```
$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
$ recipient="n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.00001 }''')
$ bitcoin-cli -named decoderawtransaction hexstring=$rawtxhex
{
"txid": "2b59c31bc232c0399acee4c2a381b564b6fec295c21044fbcbb899ffa56c3da5",
"hash": "2b59c31bc232c0399acee4c2a381b564b6fec295c21044fbcbb899ffa56c3da5",
"version": 2,
"size": 85,
"vsize": 85,
"weight": 340,
"locktime": 0,
"vin": [
{
"txid": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00001000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 e7c1345fc8f87c68170b3aa798a956c2fe6a9eff OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"
]
}
}
]
}
$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex | jq -r '.hex')
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
e70dd2aa13422d12c222481c17ca21a57071f92ff86bdcffd7eaca71772ba172
```
Pronto! Enviamos outra transação bruta, mas desta vez usando argumentos nomeados para maior clareza e redução de erros.
> :warning: **AVISO DE VERSÃO:** É aqui que o bug no Bitcoin Core 0.14 aparece: O argumento ```inputs``` no ```createrawtransaction``` tem o nome ```transactions``` incorreto. Portanto, se estiver no Bitcoin Core 0.14.0, substitua o argumento nomeado ```inputs``` por ```transactions``` para este e também para os exemplos futuros. No entanto, a partir do Bitcoin Core 0.14.1, este código deve funcionar normalmente.
## Resumo: Criando uma Transação Bruta com Argumentos Nomeados
Executando o ```bitcoin-cli``` com o argumento ```-named``` podemos usar argumentos nomeados ao invés de depender de argumentos ordenados. O comando ```bitcoin-cli help``` sempre mostrará o nome correto para cada argumento. Isso pode resultar em um código mais robusto, mais fácil de ler e menos sujeito a erros.
_À partir de agora, usaremos argumentos nomeados para todos os exemplos futuros, para maior clareza e para estabelecer as melhores práticas. No entanto, também mostraremos todos os argumentos na ordem correta. Portanto, se preferir não usar os argumentos nomeados, apenas retire o argumento ```-named``` e todos os ```name=``` que os exemplos devem continuar funcionando corretamente._
## O Que Vem Depois?
Continue "Enviando Transações no Bitcoin" na seção [§4.4: Enviando Moedas com Transações Brutas](04_4_Sending_Coins_with_a_Raw_Transaction.md).

View File

@ -0,0 +1,187 @@
# 4.4: Enviando Moedas com Transações Brutas
Conforme observado no início deste capítulo, a interface ```bitcoin-cli``` oferece três maneiras principais de enviar moedas. A seção [§4.1](04_1_Sending_Coins_The_Easy_Way.md) falou sobre como enviá-la pela primeira vez, usando o comando ```sendtoaddress```. Desde então, estamos construindo coisas mais detalhadas sobre como enviar moedas de uma segunda maneira, com transações brutas. A seção [§4.2](04_2_Creating_a_Raw_Transaction.md) nos ensinou como criar uma transação bruta, um [Prefácio](04_2__Interlude_Using_JQ.md) explicou JQ e a seção [§4.3](04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md) demonstrou os argumentos nomeados.
Agora podemos colocá-los juntos e realmente enviar fundos usando uma transação bruta.
## Criando um Endereço de Troco
Nosso exemplo de transação bruta na seção §4.2 era simples demais: enviamos um UTXO inteiro para um novo endereço. Com mais frequência, iremos desejar enviar a alguém uma quantia em dinheiro que não corresponda a um UTXO. Mas, devemos nos lembrar que o excesso de dinheiro de um UTXO que não é enviado ao destinatário se torna apenas a taxa de transação. Então, como enviar para alguém apenas uma parte de um UTXO, enquanto guardamos o resto para a gente?
A solução é _enviar_ o restante dos fundos para um segundo endereço, um endereço de troco que criamos em nossa carteira especificamente para recebê-lo:
```
$ changeaddress=$(bitcoin-cli getrawchangeaddress legacy)
$ echo $changeaddress
mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h
```
Observe que isso usa uma nova função: ```getrawchangeaddress```. É basicamente a mesma coisa que o ```getnewaddress```, mas é otimizado para uso como um endereço de troco em uma transação bruta, portanto, não faz coisas como criar entradas em nossa lista de endereços. Selecionamos novamente o endereço ```legacy```, ao invés de usar o padrão ```bech32```, simplesmente para consistência. Esta é uma situação em que teria sido seguro gerar um endereço Bech32 padrão, apenas usando ```bitcoin-cli getrawchangeaddress```, porque ele seria enviado e recebido por nós em nosso node Bitcoin Core, que tem suporte integral a isso. Mas, estamos adiantando as coisas. Mas vamos mudar para Bech32 na seção [§4.6](04_6_Creating_a_Segwit_Transaction.md).
Agora temos um endereço adicional em nossa carteira, para que possamos receber o troco de um UTXO! Para usá-lo, precisaremos criar uma transação bruta com duas saídas.
## Escolhendo UTXOs Suficientes
Nosso exemplo de transação bruta era simples também de outra maneira: assumia que havia dinheiro suficiente em um único UTXO para cobrir toda a transação. Frequentemente, esse será o caso, mas às vezes desejaremos criar transações que gastem mais dinheiro do que temos em um único UTXO. Para fazer isso, devemos criar uma transação bruta com duas (ou mais) entradas.
## Escrevendo uma Transação Bruta Real
Para resumir: a criação de uma transação bruta real para enviar moedas, às vezes, requer múltiplas entradas e, quase sempre, múltiplas saídas, uma das quais é um endereço de troco. Estaremos criando esse tipo de transação mais realista, em um exemplo que mostra um caso de uso da vida real, enviando fundos por meio da segunda metodologia do Bitcoin, as transações brutas.
Vamos usar nossos UTXOs de índice 0 e 2:
```
$ bitcoin-cli listunspent
[
[
{
"txid": "0619fecf6b2668fab1308fbd7b291ac210932602a6ac6b8cc11c7ae22c43701e",
"vout": 1,
"address": "mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d",
"label": "",
"scriptPubKey": "76a914ad1ed1c5971b2308f89c1362d4705d020a40e8e788ac",
"amount": 0.00899999,
"confirmations": 1,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/4']03eae28c93035f95a620dd96e1822f2a96e0357263fa1f87606a5254d5b9e6698f)#wwnfx2sp",
"safe": true
},
{
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
"vout": 0,
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
"label": "",
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
"amount": 0.00022000,
"confirmations": 15,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
"safe": true
},
{
"txid": "0df23a9dba49e822bbc558f15516f33021a64a5c2e48962cec541e0bcc79854d",
"vout": 0,
"address": "mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d",
"label": "",
"scriptPubKey": "76a914ad1ed1c5971b2308f89c1362d4705d020a40e8e788ac",
"amount": 0.00100000,
"confirmations": 1,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/4']03eae28c93035f95a620dd96e1822f2a96e0357263fa1f87606a5254d5b9e6698f)#wwnfx2sp",
"safe": true
}
]
```
Em nosso exemplo, enviaremos 0,009 BTC, que é (um pouco) maior do que qualquer um de nossos UTXOs. Para isso, será necessário que os combinemos e, em seguida, vamos usar nosso endereço de troco para recuperar os fundos não gastos.
### Configurando as Variáveis
Já temos as variáveis ```$changeaddress``` e ```$recipient``` dos exemplos anteriores:
```
$ echo $changeaddress
mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h
$ echo $recipient
n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi
```
Também precisamos registrar o txid e vout para cada um de nossos dois UTXOs. Tendo identificado os UTXOs que queremos gastar, podemos usar as técnicas do JQ para garantir que o acesso a eles esteja livre de erros:
```
$ utxo_txid_1=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
$ utxo_vout_1=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
$ utxo_txid_2=$(bitcoin-cli listunspent | jq -r '.[2] | .txid')
$ utxo_vout_2=$(bitcoin-cli listunspent | jq -r '.[2] | .vout')
```
### Escrevendo a Transação
Escrever a transação bruta em si é surpreendentemente simples. Tudo o que precisamos fazer é incluir um objeto JSON adicional separado por vírgula no array JSON de entradas e um par de valores-chave adicional separado por vírgula em um objeto JSON de saída.
Aqui temos um exemplo. Observe as múltiplas entradas após o argumento ```inputs``` e as múltiplas saídas após o argumento ```outputs```.
```
$ rawtxhex2=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid_1'", "vout": '$utxo_vout_1' }, { "txid": "'$utxo_txid_2'", "vout": '$utxo_vout_2' } ]''' outputs='''{ "'$recipient'": 0.009, "'$changeaddress'": 0.0009 }''')
```
Fomos _muito_ cuidadosos em calcular a quantidade. Esses dois UTXOs contêm 0,00999999 BTC. Depois de enviar 0,009 BTC, teremos 0,00099999 BTC restantes. Escolhemos 0,00009999 BTC como a nossa taxa de transação. Para acomodar essa taxa, definimos o troco como sendo 0,0009 BTC. Se não tivéssemos prestado atenção e definido nosso troco como 0,00009 BTC, essa quantidade de BTC adicional seria enviada para os mineradores! Se tivéssemos esquecido de fazer o troco, todo o excesso teria desaparecido. Portanto, novamente, _ tenha cuidado_.
Felizmente, podemos verificar três vezes com o alias ```btctxfee``` do Prefácio do JQ:
```
$ ./txfee-calc.sh $rawtxhex2
.00009999
```
### Concluindo
Agora podemos assinar, selar e entregar nossa transação, e ela será sua (e do faucet):
```
$ signedtx2=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex2 | jq -r '.hex')
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx2
e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d
```
### Esperando
Como de costume, nossas moedas estarão no fluxo por um tempo: o troco ficará indisponível até que a transação seja realmente confirmada e um novo UTXO nos seja dado.
Mas, em 10 minutos ou menos (provavelmente), teremos o dinheiro restante de volta e totalmente utilizável novamente. Por enquanto, ainda precisamos esperar:
```
$ bitcoin-cli listunspent
[
{
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
"vout": 0,
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
"label": "",
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
"amount": 0.00022000,
"confirmations": 15,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
"safe": true
}
]
```
E o troco eventualmente voltará para nós:
```
[
{
"txid": "e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d",
"vout": 1,
"address": "mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h",
"scriptPubKey": "76a91432db726320e4ad170c9c1ee83cd4d8a243c3435988ac",
"amount": 0.00090000,
"confirmations": 1,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/1'/2']02881697d252d8bf181d08c58de1f02aec088cd2d468fc5fd888c6e39909f7fabf)#p6k7dptk",
"safe": true
},
{
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
"vout": 0,
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
"label": "",
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
"amount": 0.00022000,
"confirmations": 16,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
"safe": true
}
]
```
Este também pode ser um bom momento para revisitar um explorador de blockchain, para que possamos ver mais intuitivamente como as entradas, saídas e taxas estão dispostas na transação: [e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d](https://mempool.space/pt/testnet/tx/e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d).
## Resumo: Enviando Moedas com Transações Brutas
Para enviar moedas usando transações brutas, precisamos criar uma transação bruta com uma ou mais entradas (para ter fundos suficientes) e uma ou mais saídas (para recuperar usando o troco). Então, podemos seguir nosso procedimento normal de usar o ```createrawtransaction``` com argumentos nomeados junto com o JQ, conforme descrito nas seções anteriores.
> :fire: ***Qual é o poder de enviar moedas com transações brutas?***
> _As vantagens._ Oferece maior controle. Se o nosso objetivo é escrever um programa ou script Bitcoin mais complexo, provavelmente usaremos as transações brutas para saber exatamente o que está acontecendo. Essa também é a situação mais _segura_ para usar transações brutas, porque podemos garantir que não cometeremos nenhum erro na parte da programação.
> _As desvantagens._ É muito fácil perder dinheiro. Não há avisos, bloqueios e barreiras na programação, a não ser que as criemos. Também é tudo muito misterioso. A formatação é desagradável, mesmo usando a interface ```bitcoin-cli``` que é fácil de usar, e temos que fazer muitas pesquisas e cálculos manualmente.
## O Que Vem Depois?
Veja uma forma alternativa de inserir comandos no [Prefácio: Usando Curl](04_4__Interlude_Using_Curl.md).
Ou, se preferir pular o que é francamente uma digressão, podemos aprender mais uma forma de enviar transações no Bitcoin na seção [§4.5 Enviando Moedas com Transações Brutas Automatizadas](04_5_Sending_Coins_with_Automated_Raw_Transactions.md).

View File

@ -0,0 +1,312 @@
# Prefácio: Usando Curl
O ```bitcoin-cli``` é, em última análise, apenas um invólucro. É uma forma de interagir com ```bitcoind``` a partir da linha de comando, fornecendo acesso simplificado aos seus diversos comandos RPC. Mas o RPC pode, é claro, ser acessado diretamente. É disso que iremos falar nessa seção: como nos conectarmos diretamente ao RPC com o comando ```curl```.
Não será muito usado nos próximos capítulos, mas essas informações serão importantes caso queiramos uma alternativa para acessar o ```bitcoind```.
## Conhecendo o Curl
O ```curl```, abreviação de "ver URL" ("see URL" em inglês), é uma ferramenta que nos permite acessar URLs diretamente pela linha de comando. É uma maneira fácil de interagir com servidores como o ```bitcoind```, que ficam ouvindo as portas da internet e conversam utilizando uma variedade de protocolos. O Curl também está disponível como uma biblioteca para muitas linguagens de programação, como C, Java, PHP e Python. Então, depois de saber como trabalhar com o Curl, teremos uma base sólida para usar várias APIs diferentes.
Para usar o ```curl``` com o ```bitcoind```, devemos saber três coisas: o formato padrão, o nome de usuário e senha e a porta correta.
### Conhecendo o Formato
Os comandos ```bitcoin-cli``` estão todos vinculados aos comandos RPC no ```bitcoind```. Isso torna a transição do uso de ```bitcoin-cli``` para o uso do ```curl``` muito simples. Na verdade, se olharmos qualquer uma das páginas de ajuda do ```bitcoin-cli```, veremos que eles listam não apenas os comandos ```bitcoin-cli```, mas também os comandos ```curl``` paralelos. Por exemplo, aqui temos o resultado do comando ```bitcoin-cli help getmininginfo```:
```
$ bitcoin-cli help getmininginfo
getmininginfo
Returns a json object containing mining-related information.
Result:
{ (json object)
"blocks" : n, (numeric) The current block
"currentblockweight" : n, (numeric, optional) The block weight of the last assembled block (only present if a block was ever assembled)
"currentblocktx" : n, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled)
"difficulty" : n, (numeric) The current difficulty
"networkhashps" : n, (numeric) The network hashes per second
"pooledtx" : n, (numeric) The size of the mempool
"chain" : "str", (string) current network name (main, test, regtest)
"warnings" : "str" (string) any network and blockchain warnings
}
Examples:
> bitcoin-cli getmininginfo
> curl --user myusername --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getmininginfo", "params": []}' -H 'content-type: text/plain;' http://127.0.0.1:8332/
```
E ali está o comando ```curl```, no final da tela de ajuda! Este comando um tanto longo tem quatro partes principais: (1) uma lista do nome de usuário; (2) um sinalizador ```--data-binary```; (3) um objeto JSON que diz ao ```bitcoind``` o que fazer, incluindo um array JSON com os parâmetros e; (4) um cabeçalho HTTP que inclui a URL do ```bitcoind```.
Quando estamos trabalhando com o ```curl```, muitos desses argumentos do ```curl``` permanecerão os mesmos de um comando para outro, apenas as entradas ```method``` e ```params``` no array JSON normalmente mudam. No entanto, precisaremos saber como preencher o nome do usuário e endereço da URL para que funcione, antes de mais nada!
_Sempre que não tivermos certeza sobre como usar o curl no RPC, basta usarmos a ajuda do bitcoin-cli e continuar._
### Descobrindo o Nome de Usuário
Para falar com a porta do ```bitcoind```, precisamos de um nome de usuário e senha. Eles foram criados como parte da configuração inicial do Bitcoin e podem ser encontrados no arquivo `~/.bitcoin/bitcoin.conf`.
Por exemplo, aqui está nossa configuração atual:
```
$ cat ~/.bitcoin/bitcoin.conf
server=1
dbcache=1536
par=1
maxuploadtarget=137
maxconnections=16
rpcuser=StandUp
rpcpassword=8eaf562eaf45c33c3328bc66008f2dd1
rpcallowip=127.0.0.1
debug=tor
prune=550
testnet=1
mintxfee=0.001
txconfirmtarget=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
```
Nosso nome de usuário é ```StandUp``` e nossa senha é ```8eaf562eaf45c33c3328bc66008f2dd1```.
> **ATENÇÃO:** Obviamente, não é muito seguro ter essas informações em um arquivo de texto simples. A partir do Bitcoin Core 0.12, podemos omitir o ```rpcpassword``` do arquivo ```bitcoin.conf``` e fazer com que o ```bitcoind``` gere um novo cookie sempre que iniciarmos o serviço. A desvantagem disso é que torna o uso de comandos RPC por outros aplicativos, como os detalhados neste capítulo, mais difícil. Então, vamos ficar com as informações simples do ```rpcuser``` e ```rpcpassword``` por enquanto, mas para softwares em produção, é importante considerarmos essa alteração para cookies.
A maneira segura de usar o RPC com ```bitcoind``` é a seguinte:
```
$ curl --user StandUp --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
Enter host password for user 'bitcoinrpc':
```
Conforme observado, nossa senha será solicitada.
> :link: **TESTNET vs MAINNET:** A Testnet usa uma URL com a porta 18332 e a mainnet usa uma URL com a porta 8332. Se tivermos alguma dúvida, basta olharmos nosso ```bitcoin.conf```. As configurações estão todas lá.
A maneira insegura e errada de fazer isso é a seguinte:
```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
```
> **ATENÇÃO:** Digitar a senha na linha de comando pode colocá-la na tabela de processos e/ou salvá-la em um histórico qualquer. Isso é ainda menos recomendado do que colocá-la em um arquivo, exceto para testes utilizando a testnet. Se quisermos fazer em qualquer outro lugar, precisamos nos certificar de saber o que estamos fazendo!
### Conhecendo os Comandos e os Parâmetros
Com tudo isso em mãos, estamos prontos para enviar os comandos RPC padrão com o ```curl```, mas ainda precisamos saber como incorporar os dois elementos que tendem a mudar no comando ```curl```.
O primeiro é o ```method```, que é o método RPC que está sendo utilizado. Isso geralmente deve corresponder aos nomes de comando que alimentamos no ```bitcoin-cli``` por muito tempo.
O segundo é o ```params```, que é uma array JSON de parâmetros. Eles são iguais aos argumentos (ou argumentos nomeados) que estamos usando. Eles também são a parte mais confusa do ```curl```, em grande parte porque são um array estruturado ao invés de uma simples lista.
Esta é a aparência de alguns arrays de parâmetros:
* `[]` — Um array vazio;
* `["000b4430a7a2ba60891b01b718747eaf9665cb93fbc0c619c99419b5b5cf3ad2"]` — Um array com dados;
* `["'$signedhex'"]` — Um array com uma variável;
* `[6, 9999999]` — Uma array com dois parâmetros;
* `{}` - Um objeto vazio;
* `[''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.298, "'$changeaddress'": 1.0}'']` — Um array com um array contendo um objeto e um objeto vazio.
## Obtendo Informação
Agora podemos enviar nosso primeiro comando ```curl``` acessando o RPC ```getmininginfo```:
```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
{"result":{"blocks":1772428,"difficulty":10178811.40698772,"networkhashps":91963587385939.06,"pooledtx":61,"chain":"test","warnings":"Warning: unknown new rules activated (versionbit 28)"},"error":null,"id":"curltest"}```
Note that we provided the method, `getmininginfo`, and the parameter, `[]`, but that everything else was the standard `curl` command line.
```
> **ATENÇÃO:** Se obtivermos como resultado o seguinte erro: "Failed to connect to 127.0.0.1 port 8332: Connection refused", precisamos nos certificar de que uma linha como ```rpcallowip = 127.0.0.1``` esteja configurada no ```~/.bitcoin/bitcoin.conf```. Se ainda não funcionar, precisaremos permitir o acesso à porta 18332 (ou 8332) do nosso host local. Nossa configuração padrão do [Capítulo 2: Configurando um Bitcoin-Core VPS](02_0_Setting_Up_a_Bitcoin-Core_VPS.md) deve fazer tudo isso.
O resultado é outro array JSON, que infelizmente é ruim de ler se estivermos usando o ```curl``` manualmente. Felizmente, podemos limpá-lo simplesmente usando o ```jq```:
```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 295 100 218 100 77 72666 25666 --:--:-- --:--:-- --:--:-- 98333
{
"result": {
"blocks": 1772429,
"difficulty": 10178811.40698772,
"networkhashps": 90580030969896.44,
"pooledtx": 4,
"chain": "test",
"warnings": "Warning: unknown new rules activated (versionbit 28)"
},
"error": null,
"id": "curltest"
}
```
Você verá um pouco de relatório de conectividade à medida que os dados são baixados, então, quando os dados chegarem ao ```jq```, tudo será corretamente identado. Estaremos omitindo as informações do download nos próximos exemplos.
## Manipulando Nossa Carteira
Embora já estejamos acessando o ```bitcoind``` diretamente, ainda teremos acesso à funcionalidade de carteira, porque ela está amplamente armazenada no próprio ```bitcoind```.
### Pesquisando Endereços
Usando o RPC ```getaddressesbylabel``` para listar todos os nossos endereços atuais:
```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getaddressesbylabel", "params": [""] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
{
"result": {
"mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE": {
"purpose": "receive"
},
"mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff": {
"purpose": "receive"
},
"moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B": {
"purpose": "receive"
},
"mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d": {
"purpose": "receive"
},
"tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6": {
"purpose": "receive"
},
"tb1qmtucvjtga68kgrvkl7q05x4t9lylxhku7kqdpr": {
"purpose": "receive"
}
},
"error": null,
"id": "curltest"
}
```
Este é o nosso primeiro exemplo de um parâmetro real, ```" "```. Este é o parâmetro ```label``` obrigatório para o ```getaddressesbylabel```, mas todos os nossos endereços estão sob o rótulo padrão, então nada de especial foi necessário neste momento.
O resultado é uma lista de todos os endereços que foram usados na nossa carteira. Alguns dos quais presumivelmente possuem saldo.
### Pesquisando Saldos
Use o RPC ```listunspent``` para listar os saldos que temos disponíveis:
```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
{
"result": [
{
"txid": "e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d",
"vout": 1,
"address": "mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h",
"scriptPubKey": "76a91432db726320e4ad170c9c1ee83cd4d8a243c3435988ac",
"amount": 0.0009,
"confirmations": 4,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/1'/2']02881697d252d8bf181d08c58de1f02aec088cd2d468fc5fd888c6e39909f7fabf)#p6k7dptk",
"safe": true
},
{
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
"vout": 0,
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
"label": "",
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
"amount": 0.00022,
"confirmations": 19,
"spendable": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
"safe": true
}
],
"error": null,
"id": "curltest"
}
```
Esta é quase a mesma saída que recebemos quando digitamos ```bitcoin-cli listunspent```, mostrando como as duas interfaces estão intimamente ligadas. Se nenhuma limpeza ou ajuda extra for necessária, então o ```bitcoin-cli``` apenas produzirá o RPC. Simples assim!
### Criando um Endereço
Depois de saber onde os saldos estão, a próxima etapa na elaboração de uma transação é obter um endereço de troco. Agora provavelmente já pegamos o jeito e sabemos que para os comandos RPC simples, tudo que precisamos fazer é ajustar o ```method``` no comando ```curl```:
```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
{
"result": "mrSqN37TPs89GcidSZTvXmMzjxoJZ6RKoz",
"error": null,
"id": "curltest"
}
```
Neste ponto, podemos até mesmo voltar à nossa prática padrão de salvar os resultados em variáveis com a ajuda adicional do `jq`:
```
$ changeaddress=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result')
$ echo $changeaddress
mqdfnjgWr2r3sCCeuTDfe8fJ1CnycF2e6R
```
Não precisamos nos preocupar com as informações do download. Ele irá para o ```STDERR``` e será exibido em nossa tela, enquanto os resultados irão para o ```STDOUT``` e serão salvos em nossa variável.
## Criando uma Transação
Agora estamos prontos para criar uma transação com o ```curl```.
### Preparando as Variáveis
Assim como no ```bitcoin-cli```, para criar uma transação usando o Curl com o RPC, devemos primeiro salvar nossas variáveis. A única mudança aqui é que o ```curl``` cria um objeto JSON que inclui um valor-chave ```result```, então sempre precisaremos usar o pipe (```|```) através da tag ```.result``` antes de fazer outra coisa qualquer.
Este exemplo configura nossas variáveis para usar o BTC de 1.2985 em fundos listados na primeira transação não-gasta acima:
```
$ utxo_txid=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .[0] | .txid')
$ utxo_vout=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .[0] | .vout')
$ recipient=mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf
$ changeaddress=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result')
$ echo $utxo_txid
e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d
$ echo $utxo_vout
1
$ echo $recipient
mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf
$ echo $changeaddress
n2jf3MzeFpFGa7wq8rXKVnVuv5FoNSJZ1N
```
### Criando a Transação
A transação criada com o ```curl``` é muito semelhante à transação criada com o ```bitcoin-cli```, mas com algumas diferenças sutis:
```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.0003, "'$changeaddress'": 0.0005}'']}' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
{
"result": "02000000010d6acd0356db222ca3a7ee7fa1e3044316223ceec1f64b58aeb2e0de921007e70100000000ffffffff0230750000000000001976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac50c30000000000001976a9147021efec134057043386decfaa6a6aa4ee5f19eb88ac00000000",
"error": null,
"id": "curltest"
}
```
O coração da transação é, obviamente, o array JSON ```params```, que estamos colocando em uso total pela primeira vez.
Podemos observar que todos os ```params``` estão alojados nos ```[]``` para marcar o array de parâmetros.
Nós também variamos as citações de como as coisas funcionavam no ```bitcoin-cli```, para iniciar e terminar cada array e objeto dentro do array ```params``` com ```''``` ao invés do tradicional ```'''```. Isso porque todo o conjunto de argumentos JSON já tem um ```'``` em torno dele. Como de costume, basta dar uma olhada na bizarra citação do shell e se acostumar com isso.
No entanto, há uma última coisa a ser observada neste exemplo, e pode ser _enlouquecedor_ se não tivermos percebido. Quando executamos um comando ```createrawtransaction``` com ```bitcoin-cli```, o array JSON de entradas e o objeto JSON de saídas eram parâmetros distintos, portanto, foram separados por um espaço. Agora, porque eles são parte do array JSON ```params```, eles são separados por uma vírgula (```,```). Se não tivéssemos percebido isso obteríamos um ```parse error``` sem muitas informações.
> **ATENÇÃO:** Todo mundo já teve problemas para depurar o ```curl```, não é mesmo? Para resolver isso basta adicionar o argumento ```--trace-ascii/tmp/foo```. Informações completas sobre o que está sendo enviado ao servidor serão salvas em ```/tmp/foo``` (ou qualquer nome de arquivo que quisermos informar).
Depois de verificarmos se as coisas estão funcionando, provavelmente desejaremos salvar o código hexadecimal em uma variável:
```
$ hexcode=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.0003, "'$changeaddress'": 0.0005}'']}' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result')
```
### Assinando e Enviando
Assinar e enviar a nossa transação usando ```curl``` é bem simples, basta usar os seguintes comandos do RPC ```signrawtransactionwithwallet``` e ```sendrawtransaction```:
```
$ signedhex=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransactionwithwallet", "params": ["'$hexcode'"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .hex')
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "sendrawtransaction", "params": ["'$signedhex'"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
{
"result": "eb84c5008038d760805d4d9644ace67849542864220cb2685a1ea2c64176b82d",
"error": null,
"id": "curltest"
}
```
## Resumo: Acessando o Bitcoind com Curl
Terminando esta seção, podemos sentir que acessar o ```bitcoind``` através de ```curl``` é muito parecido com acessá-lo através de ```bitcoin-cli```, porém, é mais complicado. E estamos certos. O ```bitcoin-cli``` tem funcionalidade RPC bem completa, então qualquer coisa que fizermos através do ```curl``` provavelmente poderemos fazer através do ```bitcoin-cli```. E é por isso que vamos continuar nos concentrando no ```bitcoin-cli``` após esta digressão.
Mas ainda há razões para usar ```curl``` ao invés do ```bitcoin-cli```:
_Qual é o poder do curl?_ Obviamente, o ```curl``` elimina um nível intermediário. Ao invés de trabalhar com o ```bitcoin-cli```, que envia comandos RPC para o ```bitcoind```, estamos enviando esses comandos RPC diretamente para ele. Isso permite uma programação mais robusta, porque não precisamos nos preocupar com as coisas inesperadas que o ```bitcoin-cli``` pode fazer ou como isso pode mudar com o tempo. No entanto, também estamos dando os primeiros passos para usar uma linguagem de programação mais abrangente do que as opções pobres oferecidas por um script de shell. Como veremos nos últimos capítulos deste livro, podemos realmente ver que as bibliotecas curl são outras funções que acessam os comandos RPC em uma variedade de linguagens de programação: mas isso ainda está muito longe.
## O Que Vem Depois?
Aprenda mais uma maneira de enviar transações no Bitcoin com [§4.5 Enviando Moedas com Transações Brutas Automatizadas](04_5_Sending_Coins_with_Automated_Raw_Transactions.md).

View File

@ -0,0 +1,171 @@
# 4.5: Enviando Moedas com Transações Brutas Automatizadas
Este capítulo apresenta três maneiras de enviar fundos por meio da interface cli do Bitcoin. A seção [§4.1](04_1_Sending_Coins_The_Easy_Way.md) descreveu como fazer isso com um comando simples e a seção [§4.4](04_4_Sending_Coins_with_a_Raw_Transaction.md) detalhou como usar uma transação bruta mais perigosa. Esta seção fica no meio termo de ambas, mostrando como tornar as transações brutas mais simples e seguras.
## Deixando o Bitcoin Fazer os Cálculos Para Nós
A metodologia para transações brutas automatizadas é simples: criamos uma transação bruta, mas usamos o comando ```fundrawtransaction``` para pedir ao bitcoind para executar os cálculos para nós.
Para usar este comando, precisaremos garantir que nosso arquivo ```~/.bitcoin/bitcoin.conf``` contenha as variáveis racionais para calcular as taxas de transação. Podemos consultar a seção [§4.1: Enviando Moedas da Maneira Fácil](04_1_Sending_Coins_The_Easy_Way.md) para obter mais informações sobre isso.
Vamos usar números conservadores, por isso sugerimos adicionar o seguinte ao `bitcoin.conf`:
```
mintxfee=0.0001
txconfirmtarget=6
```
Para manter o tutorial em movimento (e para movimentarmos nosso dinheiro rapidamente), sugerimos o seguinte:
```
mintxfee=0.001
txconfirmtarget=1
```
## Criando uma Transação Bruta
Para usar o ```fundrawtransaction``` primeiro precisamos criar uma transação bruta básica que liste _nenhuma_ entrada e _nenhuma_ mudança de endereço. Apenas listaremos o nosso destinatário e quanto desejamos enviar, neste caso ```$recipient``` e ```0,0002``` BTC.
```
$ recipient=n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi
$ unfinishedtx=$(bitcoin-cli -named createrawtransaction inputs='''[]''' outputs='''{ "'$recipient'": 0.0002 }''')
```
## Financiando Nossa Transação Bruta
Dizemos ao ```bitcoin-cli``` para financiar essa transação básica:
```
$ bitcoin-cli -named fundrawtransaction hexstring=$unfinishedtx
{
"hex": "02000000012db87641c6a21e5a68b20c226428544978e6ac44964d5d8060d7388000c584eb0100000000feffffff02204e0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac781e0000000000001600140cc9cdcf45d4ea17f5227a7ead52367aad10a88400000000",
"fee": 0.00022200,
"changepos": 1
}
```
Isso fornece muitas informações úteis, mas uma vez que tenhamos certeza de como funciona, vamos querer usar o JQ para salvar nosso hex em uma variável, como de costume:
```
$ rawtxhex3=$(bitcoin-cli -named fundrawtransaction hexstring=$unfinishedtx | jq -r '.hex')
```
## Verificando Nossa Transação Financiada
Parece mágica, então nas primeiras vezes que usarmos o ```fundrawtransaction```, provavelmente vamos querer verificá-la.
Vamos executar o comando ```decoderawtransaction``` para mostrar que a transação bruta agora está disposta corretamente, usando um ou mais dos nossos UTXOs e enviando fundos excedentes de volta para um endereço de troco:
```
$ bitcoin-cli -named decoderawtransaction hexstring=$rawtxhex3
{
"txid": "b3b4c2057dbfbef6690e975ede92fde805ddea13c730f58401939a52c9ac1b99",
"hash": "b3b4c2057dbfbef6690e975ede92fde805ddea13c730f58401939a52c9ac1b99",
"version": 2,
"size": 116,
"vsize": 116,
"weight": 464,
"locktime": 0,
"vin": [
{
"txid": "eb84c5008038d760805d4d9644ace67849542864220cb2685a1ea2c64176b82d",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.00020000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 e7c1345fc8f87c68170b3aa798a956c2fe6a9eff OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"
]
}
},
{
"value": 0.00007800,
"n": 1,
"scriptPubKey": {
"asm": "0 a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
"hex": "0014a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r"
]
}
}
]
}
```
Uma coisa de interesse aqui é o endereço de troco, que é o segundo ```vout```. Observe que é um endereço ```tb1```, o que significa que é do tipo Bech32. Quando demos ao Bitcoin Core a capacidade total de gerenciar as alterações, ele o fez usando o tipo de endereço padrão, Bech32, e funcionou bem. É por isso que nossa mudança para endereços SegWit na seção [§4.6](04_6_Creating_a_Segwit_Transaction.md) realmente não é um grande negócio, mas existem algumas dicas para uso mais amplo, sobre as quais falaremos lá.
Embora tenhamos visto a taxa na saída de ```fundrawtransaction```, ela não pode ser visível aqui. No entanto, podemos verificar isso com o script JQ ```txfee-calc.sh``` criado na seção [Prefácio: Usando JQ](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/04_2__Interlude_Using_JQ.md):
```
$ ~/txfee-calc.sh $rawtxhex3
.000222
```
Finalmente, podemos usar o ```getaddressinfo``` para ver se o endereço de troco gerado realmente nos pertence:
```
$ bitcoin-cli -named getaddressinfo address=tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r
{
"address": "tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r",
"scriptPubKey": "0014a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
"ismine": true,
"solvable": true,
"desc": "wpkh([d6043800/0'/1'/10']038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec5)#zpv26nar",
"iswatchonly": false,
"isscript": false,
"iswitness": true,
"witness_version": 0,
"witness_program": "a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
"pubkey": "038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec5",
"ischange": true,
"timestamp": 1592335137,
"hdkeypath": "m/0'/1'/10'",
"hdseedid": "fdea8e2630f00d29a9d6ff2af7bf5b358d061078",
"hdmasterfingerprint": "d6043800",
"labels": [
]
}
```
Observe o conteúdo do `ismine`.
## Enviando a Transação Financiada
Neste ponto, podemos assinar e enviar a transação normalmente.
```
$ signedtx3=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex3 | jq -r '.hex')
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx3
8b9dd66c999966462a3d88d6ac9405d09e2aa409c0aa830bdd08dbcbd34a36fa
```
Em alguns minutos, teremos o nosso troco de volta:
```
$ bitcoin-cli listunspent
[
{
"txid": "8b9dd66c999966462a3d88d6ac9405d09e2aa409c0aa830bdd08dbcbd34a36fa",
"vout": 1,
"address": "tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r",
"scriptPubKey": "0014a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
"amount": 0.00007800,
"confirmations": 1,
"spendable": true,
"solvable": true,
"desc": "wpkh([d6043800/0'/1'/10']038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec5)#zpv26nar",
"safe": true
}
]
```
## Resumo: Enviando Moedas com Transações Brutas Automatizadas
Se formos enviar fundos usando transações brutas, então o ```fundrawtransaction``` oferece uma boa alternativa onde taxas, entradas e saídas são calculadas para nós, para que não percamos acidentalmente muito dinheiro.
> :fire: ***Qual é o poder de enviar moedas com transações brutas automatizadas?***
> _As vantagens._ Proporciona um bom meio termo. Se estamos enviando fundos manualmente e o ```sendtoaddress``` não oferece controle suficiente por qualquer motivo, podemos obter algumas das vantagens das transações brutas sem os perigos dela. Essa metodologia deve ser usada sempre que possível se estivermos enviando transações brutas manualmente.
> _As desvantagens._ É uma mistura. Embora existam algumas opções adicionais no ```fundrawtransaction``` que não foram mencionadas aqui, nosso controle ainda é limitado. Provavelmente, nunca desejaríamos usar esse método se formos escrever um programa cujo objetivo é saber exatamente o que está acontecendo.
## O Que Vem Depois?
Vamos concluir o capítulo "Enviando Transações no Bitcoin" com a seção [§4.6: Criando uma Transação SegWit](04_6_Creating_a_Segwit_Transaction.md).

View File

@ -0,0 +1,288 @@
# 4.6: Criando uma Transação SegWit
> :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.
Era uma vez, nos céus do Bitcoin, uma guerra entre os tamanhos de blocos. As taxas disparavam e os usuários estavam preocupados se o Bitcoin podia realmente escalar. Os desenvolvedores do Bitcoin Core relutaram em simplesmente aumentar o tamanho do bloco, mas chegaram a um acordo: fizeram o SegWit, que significa Segregated Witness. Segregated Witness é uma maneira elegante de dizer "Assinatura Separada". Ele cria novos tipos de transações que removem assinaturas no final da transação. Ao combinar isso com o aumento dos tamanhos de bloco que são visíveis apenas para nodes atualizados, o SegWit resolveu os problemas de dimensionamento do Bitcoin na época e também resolveu um bug de maleabilidade desagradável, tornando o dimensionamento ainda melhor para protocolos de segunda camada, como a Lightning Network.
A sacada? O SegWit usa endereços diferentes, alguns dos quais são compatíveis com nodes mais antigos, ao passo que outros não.
> :warning: **AVISO DE VERSÃO:** O SegWit foi introduzido no BitCoin 0.16.0, que foi descrito na época como tendo "suporte total". Dito isso, havia algumas falhas na integração com o ```bitcoin-cli``` na época, que impediam a assinatura de funcionar corretamente em novos endereços P2SH-SegWit. O endereço Bech32, não compatível com versões anteriores, também foi introduzido no Bitcoin 0.16.0 e se tornou o tipo de endereço padrão no Bitcoin 0.19.0. Toda essa funcionalidade deve estar totalmente funcional em relação às funções ```bitcoin-cli``` (e, portanto, devem funcionar completamente neste tutorial).
> O problema está em interagir com o mundo. Todos devem ser capazes de enviar para um endereço P2SH-SegWit porque foi construído propositadamente para suportar compatibilidade com as versões anteriores, envolvendo a funcionalidade SegWit em um Script Bitcoin. O mesmo não é verdade para endereços Bech32: Se alguém nos disser que não pode enviar para o nosso endereço Bech32 precisaremos gerar um endereço ```legacy``` ou P2SH-SegWit para fazer a transação. (Muitos sites, principalmente as corretoras, também não podem gerar ou receber em endereços SegWit, particularmente endereços Bech32, mas isso é um problema totalmente diferente e não afeta o uso delas).
## Compreendendo uma Transação SegWit
Em transações clássicas, as informações de assinatura (witness) eram armazenadas no meio da transação, enquanto nas transações SegWit, elas ficam na parte inferior. Isso anda de mãos dadas com os aumentos de tamanho do bloco que foram introduzidos na atualização do SegWit. O tamanho do bloco foi aumentado de 1 mega para um valor variável com base em quantas transações SegWit estão em um bloco, começando em 1 mega (sem transações SegWit) e podendo chegar a 4 megas (caso todas as transações sejam SegWit). Este tamanho variável foi criado para acomodar os nodes clássicos, de forma que tudo permaneça compatível com as versões anteriores. Se um node clássico vê uma transação SegWit, ele joga fora as informações da witness (resultando em um bloco de tamanho menor, abaixo do antigo limite de 1 mega), enquanto se um novo node vê uma transação SegWit, ele mantém as informações da witness (resultando em um maior tamanho de bloco, até o novo limite de 4 megas).
Portanto, acabamos de responder o quê são e como funcionam as transações SegWit. Não que precisemos saber disso para usá-las. A maioria das transações na rede Bitcoin são SegWit. Elas são aquilo que iremos utilizar nativamente para as transações e recebimentos de bitcoins. A este ponto, os detalhes não são mais relevantes do que os detalhes de como grande parte do Bitcoin funciona.
## Criando um Endereço SegWit
Criamos um endereço SegWit da mesma maneira que qualquer outro endereço, com os comandos ```getnewaddress``` e ```getrawchangeaddress```.
Se precisarmos criar um endereço para alguém que não pode enviar para os endereços Bech32 mais recentes, podemos usar um endereço ```p2sh-segwit```:
```
$ bitcoin-cli -named getnewaddress address_type=p2sh-segwit
2N5h2r4karVqN7uFtpcn8xnA3t5cbpszgyN
```
Se conseguirmos ver um endereço com o prefixo "2" significa que fizemos tudo certo.
> :link: **TESTNET vs MAINNET:** "3" para a Mainnet.
No entanto, se a pessoa com quem estamos interagindo tem um node com uma versão mais nova, ela poderá enviar para um endereço Bech32, que criamos usando os comandos da maneira padrão:
```
$ bitcoin-cli getnewaddress
tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6
```
Como já vimos, os endereços de troco gerados a partir do ```bitcoin-cli``` interagem bem com os endereços Bech32, então não há motivo nenhum para usar o sinalizador ```legacy``` lá também:
```
$ bitcoin-cli getrawchangeaddress
tb1q05wx5tyadm8qe83exdqdyqvqqzjt3m38vfu8ff
```
Aqui, podemos observar que o prefixo "tb1" exclusivo denota que o endereço é um Bech32.
> :link: **TESTNET vs MAINNET:** "bc1" para a mainnet.
O bitcoin-cli não se importa com o tipo de endereço que estamos utilizando. Podemos executar um comando como ```listaddressgroupings``` que ele irá misturar os endereços livremente, não importando os tipos:
```
$ bitcoin-cli listaddressgroupings
[
[
[
"mfsiRhxbQxcD7HLS4PiAim99oeGyb9QY7m",
0.01000000,
""
]
],
[
[
"mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
0.00000000,
""
],
[
"tb1q6dak4e9fz77vsulk89t5z92l2e0zm37yvre4gt",
0.00000000
]
],
[
[
"mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
0.00022000,
""
]
],
[
[
"mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h",
0.00000000
],
[
"mqjrdY5raxKzXQf5t2VvVvzhvFAgersu9B",
0.00000000
],
[
"mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d",
0.00000000,
""
],
[
"tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r",
0.00007800
]
],
[
[
"mpVLL7iqPr4d7BJkEG54mcdm7WmrAhaW6q",
0.01000000,
""
]
],
[
[
"tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6",
0.01000000,
""
]
]
]
```
## Enviando uma Transação SegWit da Maneira Fácil
Então, como enviamos uma transação Segwit? Exatamente como qualquer outra transação. Não importa se o UTXO é SegWit, o endereço é SegWit ou alguma combinação dos dois. Podemos ter a certeza que o ```bitcoin-cli``` irá fazer a coisa certa. Embora possamos perceber algumas diferenças nos endereços, eles não importam para interagir com as coisas no nível do ```bitcoin-cli``` ou do RPC. (E esta é uma das vantagens de usar a linha de comando e a interface do RPC, conforme sugerido neste tutorial: os especialistas já fizeram o trabalho duro para nós, incluindo coisas como enviar para endereços legacy e Bech32. Acabamos usando essa funcionalidade para nosso próprio benefício).
Aqui está um exemplo de um envio para um endereço SegWit, da maneira fácil:
```
$ bitcoin-cli sendtoaddress tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx 0.005
854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42
```
Se olhar para a nossa transação, podemos ver o uso do endereço Bech32:
```
$ bitcoin-cli gettransaction txid="854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42" verbose=true
{
"amount": -0.00500000,
"fee": -0.00036600,
"confirmations": 0,
"trusted": true,
"txid": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
"walletconflicts": [
],
"time": 1592948795,
"timereceived": 1592948795,
"bip125-replaceable": "no",
"details": [
{
"address": "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx",
"category": "send",
"amount": -0.00500000,
"vout": 1,
"fee": -0.00036600,
"abandoned": false
}
],
"hex": "0200000002114d5a4c3b847bc796b2dc166ca7120607b874aa6904d4a43dd5f9e0ea79d4ba010000006a47304402200a3cc08b9778e7b616340d4cf7841180321d2fa019e43f25e7f710d9a628b55c02200541fc200a07f2eb073ad8554357777d5f1364c5a96afe5e77c6185d66a40fa7012103ee18c598bafc5fbea72d345329803a40ebfcf34014d0e96aac4f504d54e7042dfeffffffa71321e81ef039af490251379143f7247ad91613c26c8f3e3404184218361733000000006a47304402200dd80206b57beb5fa38a3c3578f4b0e40d56d4079116fd2a6fe28e5b8ece72310220298a8c3a1193ea805b27608ff67a2d8b01e347e33a4222edfba499bb1b64a31601210339c001b00dd607eeafd4c117cfcf86be8efbb0ca0a33700cffc0ae0c6ee69d7efeffffff026854160000000000160014d591091b8074a2375ed9985a9c4b18efecfd416520a1070000000000160014751e76e8199196d454941c45d1b3a323f1433bd6c60e1b00",
"decoded": {
"txid": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
"hash": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
"version": 2,
"size": 366,
"vsize": 366,
"weight": 1464,
"locktime": 1773254,
"vin": [
{
"txid": "bad479eae0f9d53da4d40469aa74b8070612a76c16dcb296c77b843b4c5a4d11",
"vout": 1,
"scriptSig": {
"asm": "304402200a3cc08b9778e7b616340d4cf7841180321d2fa019e43f25e7f710d9a628b55c02200541fc200a07f2eb073ad8554357777d5f1364c5a96afe5e77c6185d66a40fa7[ALL] 03ee18c598bafc5fbea72d345329803a40ebfcf34014d0e96aac4f504d54e7042d",
"hex": "47304402200a3cc08b9778e7b616340d4cf7841180321d2fa019e43f25e7f710d9a628b55c02200541fc200a07f2eb073ad8554357777d5f1364c5a96afe5e77c6185d66a40fa7012103ee18c598bafc5fbea72d345329803a40ebfcf34014d0e96aac4f504d54e7042d"
},
"sequence": 4294967294
},
{
"txid": "33173618421804343e8f6cc21316d97a24f7439137510249af39f01ee82113a7",
"vout": 0,
"scriptSig": {
"asm": "304402200dd80206b57beb5fa38a3c3578f4b0e40d56d4079116fd2a6fe28e5b8ece72310220298a8c3a1193ea805b27608ff67a2d8b01e347e33a4222edfba499bb1b64a316[ALL] 0339c001b00dd607eeafd4c117cfcf86be8efbb0ca0a33700cffc0ae0c6ee69d7e",
"hex": "47304402200dd80206b57beb5fa38a3c3578f4b0e40d56d4079116fd2a6fe28e5b8ece72310220298a8c3a1193ea805b27608ff67a2d8b01e347e33a4222edfba499bb1b64a31601210339c001b00dd607eeafd4c117cfcf86be8efbb0ca0a33700cffc0ae0c6ee69d7e"
},
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.01463400,
"n": 0,
"scriptPubKey": {
"asm": "0 d591091b8074a2375ed9985a9c4b18efecfd4165",
"hex": "0014d591091b8074a2375ed9985a9c4b18efecfd4165",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1q6kgsjxuqwj3rwhkenpdfcjccalk06st9z0k0kh"
]
}
},
{
"value": 0.00500000,
"n": 1,
"scriptPubKey": {
"asm": "0 751e76e8199196d454941c45d1b3a323f1433bd6",
"hex": "0014751e76e8199196d454941c45d1b3a323f1433bd6",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx"
]
}
}
]
}
}
```
Na verdade, ambos ```vouts``` usam endereços Bech32: o nosso destinatário e o endereço de troco gerado automaticamente.
Mas quando retrocedemos nosso ```vin```, descobrimos que veio de um endereço legacy. Porque isso não importa:
```
$ bitcoin-cli -named gettransaction txid="33173618421804343e8f6cc21316d97a24f7439137510249af39f01ee82113a7"
{
"amount": 0.01000000,
"confirmations": 43,
"blockhash": "00000000000000e2365d2f814d1774b063d9a04356f482010cdfdd537b1a24bb",
"blockheight": 1773212,
"blockindex": 103,
"blocktime": 1592937103,
"txid": "33173618421804343e8f6cc21316d97a24f7439137510249af39f01ee82113a7",
"walletconflicts": [
],
"time": 1592936845,
"timereceived": 1592936845,
"bip125-replaceable": "no",
"details": [
{
"address": "mpVLL7iqPr4d7BJkEG54mcdm7WmrAhaW6q",
"category": "receive",
"amount": 0.01000000,
"label": "",
"vout": 0
}
],
"hex": "020000000001016a66efa334f06e2c54963e48d049a35d7a1bda44633b7464621cae302f35174a0100000017160014f17b16c6404e85165af6f123173e0705ba31ec25feffffff0240420f00000000001976a914626ab1ca41d98f597d18d1ff8151e31a40d4967288acd2125d000000000017a914d5e76abfe5362704ff6bbb000db9cdfa43cd2881870247304402203b3ba83f51c1895b5f639e9bfc40124715e2495ef2c79d4e49c0f8f70fbf2feb02203d50710abe3cf37df4d2a73680dadf3cecbe4f2b5d0b276dbe7711d0c2fa971a012102e64f83ee1c6548bcf44cb965ffdb803f30224459bd2e57a5df97cb41ba476b119b0e1b00"
}
```
## Enviando uma Transação SegWit da Maneira Difícil
Da mesma forma, podemos financiar uma transação com um endereço Bech32, sem nenhuma diferença em relação às técnicas que aprendemos até agora. Aqui está uma maneira exata de fazer isso com uma transação bruta completa:
```
$ changeaddress=$(bitcoin-cli getrawchangeaddress)
$ echo $changeaddress
tb1q4xje3mx9xn7f8khv7p69ekfn0q72kfs8x3ay4j
$ bitcoin-cli listunspent
[
...
{
"txid": "003bfdca5578c0045a76768281f05d5e6f57774be399a76f387e2a0e99e4e452",
"vout": 0,
"address": "tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6",
"label": "",
"scriptPubKey": "0014a226e1dfd08537b02de04f667a49bd46f9b9f578",
"amount": 0.01000000,
"confirmations": 5,
"spendable": true,
"solvable": true,
"desc": "wpkh([d6043800/0'/0'/5']0327dbe2d58d9ed2dbeca28cd26e18f48aa94c127fa6fb4b60e4188f6360317640)#hd66hknp",
"safe": true
}
]
$ recipient=tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx
$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[2] | .txid')
$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[2] | .vout')
$ echo $utxo_txid $utxo_vout
003bfdca5578c0045a76768281f05d5e6f57774be399a76f387e2a0e99e4e452 0
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.002, "'$changeaddress'": 0.007 }''')
$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex | jq -r '.hex')
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
e02568b706b21bcb56fcf9c4bb7ba63fdbdec1cf2866168c4f50bc0ad693f26c
```
Tudo funciona exatamente da mesma forma que outros tipos de transações!
### Reconhecendo o Novo Descritor
Se olharmos o campo ```desc```, notaremos que o endereço SegWit tem um descritor de estilo diferente daqueles encontrados na seção [§3.5: Compreendendo o Descritor](03_5_Understanding_the_Descriptor.md). Um descritor legacy descrito nessa seção se parecia com algo assim: `pkh ([d6043800 / 0 '/ 0' / 18 '] 03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388) # 4ahsl9pk`. Nosso novo descritor SegWit se parece mais com isso: `wpkh ([d6043800 / 0 '/ 0' / 5 '] 0327dbe2d58d9ed2dbeca28cd26e18f48aa94c127fa6fb4b60e4188f6360317640) # hd66hknp" `.
A grande diferença que precisamos notar é que a função mudou. Anteriormente, era ```pkh```, que é um endereço padrão de chave pública com hash P2PKH. Ao invés disso, o endereço SegWit é ```wpkh```, o que significa que é um endereço SegWit P2WPKH nativo. Isto destaca o :fire: ***poder dos descritores***. Eles descrevem como criar um endereço a partir de uma chave ou outra informação, com as funções definindo de forma inequívoca como fazer o endereço com base em seu tipo.
## Resumo: Criando uma Transação SegWit
Realmente não há complexidade para criar transações SegWit. Internamente, elas são estruturadas de forma diferente das transações legacy, mas na linha de comando não existe diferença: apenas usamos um endereço com um prefixo diferente. A única coisa a ser observada é que algumas pessoas podem não conseguir enviar para um endereço Bech32 se estiverem usando um software obsoleto.
> :fire: ***Qual é o poder de enviar transações com SegWit?***
> _As vantagens._ As transações SegWit são menores e, portanto, serão mais baratas de serem enviadas do que as transações legacy devido às taxas mais baixas. O Bech32 diminui essa vantagem e também cria endereços que são mais difíceis de errar durante a transcrição, e isso é muito importante, visto que o erro do usuário é uma das maneiras mais prováveis de perderem seus bitcoins.
> _As desvantagens._ Os endereços SegWit não tem suporte em nodes Bitcoin obsoletos. Em particular, as pessoas podem não conseguir enviar para o nosso endereço Bech32.
## O Que Vem Depois?
Vamos avançar mais um pouco no "bitcoin-cli" com o [Capítulo 5: Controlando Transações no Bitcoin](05_0_Controlling_Bitcoin_Transactions.md).

View File

@ -0,0 +1,23 @@
# Capítulo 5: Controlando Transações no Bitcoin
O envio de uma transação nem sempre termina com um "viveram felizes para sempre". Usando os protocolos RBF (Replace-By-Fee, ou Substituindo-A -Taxa no português) e CPFP (Child-Pays-For-Parent, ou Filho-Paga-Pelo-Pai), um desenvolvedor pode continuar a controlar a transação após ela ter sido enviada, para melhorar a eficiência ou para recuperar transações que estava presas na _mempool_. Esses métodos irão começar a mostrar o verdadeiro poder do Bitcoin.
## Objetivos deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Decidir se o RBF ou o CPFP pode ajudar uma transação;
* Criar uma transação de substituição usando o RBF;
* Criar novas transações usando o protocolo CPFP.
Os objetivos secundários do capítulo incluem a capacidade de:
* Entender a Mempool;
* Entender a diferença entre o RBF e o CPFP;
* Planejar a taxa do RBF.
## Tabela de Conteúdo
* [Seção 1: Atentando-se para Transações Presas](05_1_Watching_for_Stuck_Transactions.md)
* [Seção 2: Reenviando uma Transação com RBF](05_2_Resending_a_Transaction_with_RBF.md)
* [Seção 3: Financiando uma Transação com CPFP](05_3_Funding_a_Transaction_with_CPFP.md)

View File

@ -0,0 +1,59 @@
# 5.1: Atentando-se para Transações Presas
Às vezes, uma transação de Bitcoin pode ficar presa. Isso normalmente ocorre porque não havia taxa de transação suficiente, mas também pode ser devido a uma falha da rede ou do software.
## Observando as Transações Enviadas
Nós devemos _sempre_ observar as transações para garantir que tenham sido encerradas. O ```bitcoin-cli listtransactions``` mostrará todas as nossas transações de entrada e saída, enquanto o ```bitcoin-cli gettransaction``` juntamente com um txid, irá mostrar uma transação específica.
Abaixo temos uma transação que não foi incluída em um bloco. Podemos garantir isso porque não temos nenhuma confirmação.
```
$ bitcoin-cli -named gettransaction txid=fa2ddf84a4a632586d435e10880a2921db6310dfbd6f0f8f583aa0feacb74c8e
{
"amount": -0.00020000,
"fee": -0.00001000,
"confirmations": 0,
"trusted": true,
"txid": "fa2ddf84a4a632586d435e10880a2921db6310dfbd6f0f8f583aa0feacb74c8e",
"walletconflicts": [
],
"time": 1592953220,
"timereceived": 1592953220,
"bip125-replaceable": "no",
"details": [
{
"address": "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx",
"category": "send",
"amount": -0.00020000,
"vout": 0,
"fee": -0.00001000,
"abandoned": false
}
],
"hex": "02000000014cda1f42a1bd39d8d0ff5958a804bc2bc548b71d7ceadbde53ea15aeaf1e2691000000006a473044022016a7a9f045a0f6a52129f48adb7da35c2f54a0741d6614e9d55b8a3bc3e1490a0220391e9085a3697bc790e94bb924d5310e16f23489d9c600864a32674e871f523c01210278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132ffffffff02204e000000000000160014751e76e8199196d454941c45d1b3a323f1433bd6e8030000000000001600146c45d3afa8762086c4bd76d8a71ac7c976e1919600000000"
```
Uma transação pode ser considerada presa se permanecer nesse estado por um longo período de tempo. A tempos atrás, podíamos ter a certeza de que todas as transações iriam ser confirmadas _eventualmente_. Mas, isso não é mais verdade devido ao aumento exponencial do uso do Bitcoin. Agora, se uma transação ficar travada por muito tempo, ela sairá da mempool e, em seguida, será esquecida para sempre da rede Bitcoin.
> :book: ***O que é a mempool?*** A Mempool (ou Piscina de Memória) é um local onde todas as transações não confirmadas em um node bitcoin ficam. Estas são as transações que um node recebeu da rede P2P que ainda não estão incluídas em um bloco. Cada node bitcoin pode ter um conjunto ligeiramente diferente de transações em sua mempool: Transações diferentes podem ter sido propagadas para um node específico. Isso depende de quando o node foi iniciado pela última vez e também os limites de tamanho. Quando um minerador faz um bloco, ele usa as transações da mempool. Então, quando um bloco é verificado, todos os mineradores removem essas transações da mempool. A partir do Bitcoin 0.12, as transações não confirmadas também podem expirar na mempool se forem antigas o suficiente, normalmente o tempo é de 72 horas. No caso das versões 0.14.0 o tempo foi aumentado para 2 semanas. As pools de mineração podem ter seus próprios mecanismos de gerenciamento da mempool.
Esta lista tem de todas as [transações não confirmadas](https://blockchain.info/unconfirmed-transactions) e pode não corresponder a nenhuma mempool de um node específico, mas pode ser considerada (principalmente) um superconjunto de todas elas.
## Decidindo o que fazer
Se sua transação ficar paralisada por mais tempo do que esperamos, normalmente podemos fazer uma dessas quatro coisas:
**1. Esperar até que seja confirmada.** Se enviamos a transação com uma taxa baixa ou média, ela deve ser processada cedo ou tarde. Conforme mostrado no site [Mempool Space](https://mempool.space), aqueles com taxas mais baixas _irão esperar mais_. (Vamos dar uma olhada na transação mais à esquerda e ver quanto tempo ela está esperando e quanto ela pagou de taxa).
**2. Esperar até que seja expirada.** Se acidentalmente enviamos uma transação sem taxa, ou se colocamos uma taxa muito baixa em um momento de congestionamento da rede, então nossa transação pode nunca ser concluída. No entanto, nossos bitcoins não serão perdidos. Contanto que não tenhamos uma carteira que fique reenviando propositalmente transações não confirmadas, ela deve ser eliminada da mempool em aproximadamente duas semanas, e então podemos tentar novamente utilizando valores mais altos nas taxas.
**3. Usar o RBF como sendo o remetente.** Se formos nós quem estamos enviando a transação e optarmos por usar o RBF (Replace-By-Fee), podemos tentar novamente com uma taxa mais alta. Podemos consultar a sessão [§5.2: Reenviando uma transação com o RBF](05_2_Resending_a_Transaction_with_RBF.md) para sabermos mais sobre isso.
**4. Use o CPFP como sendo o destinatário.** Se nós formos os recebedores do saldo, podemos usar o CPFP (Child-Pays-For-Parent) para usar a transação não confirmada como um input para uma nova transação. Podemos consultar a sessão [§5.3: Financiando uma transação com o CPFP](05_3_Funding_a_Transaction_with_CPFP.md).
## Resumo: Atentando-se para Transações Presas
Esta é uma introdução ao poder das transações do Bitcoin. Se sabemos que uma transação está presa, podemos decidir como liberá-la com recursos como o RBF ou o CPFP.
## O Que Vem Depois?
Continuemos "Controlando Transações no Bitcoin" com a sessão [§5.2: Reenviando uma Transação com RBF](05_2_Resending_a_Transaction_with_RBF.md).

View File

@ -0,0 +1,214 @@
# 5.2: Reenviando uma Transação com RBF
Se a nossa transação Bitcoin travar e formos a parte que está enviando o saldo, podemos reenviá-la usando o RBF (Replace-By-Fee). No entanto, isso não é tudo que o RBF pode fazer: Geralmente é um recurso poderoso que permite aos remetentes do Bitcoin recriar transações por vários motivos.
> :warning: **AVISO DE VERSÃO:** Esta é uma inovação do Bitcoin Core v0.12.0, que atingiu a maturidade total na carteira do Bitcoin Core na versão 0.14.0. Obviamente, a maioria das pessoas já deveria estar usando-a.
## Optando pelo RBF
O RBF é um recurso opcional do Bitcoin. As transações só são elegíveis para usar o RBF se tiverem sido criadas com um sinalizador RBF especial. Isso é feito configurando qualquer um dos números de sequência UTXO da transação (que normalmente são configurados automaticamente), de modo que seja maior que 0 e menor que 0xffffffff-1 (4294967294).
Isso pode ser feito simplesmente adicionando uma variável ```sequence``` às nossas entradas do UTXO:
```
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "sequence": 1 } ]''' outputs='''{ "'$recipient'": 0.00007658, "'$changeaddress'": 0.00000001 }''')
```
Obviamente, devemos assinar e enviar nossa transação, como fazemos normalmente:
```
$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex | jq -r '.hex')
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
5b953a0bdfae0d11d20d195ea43ab7c31a5471d2385c258394f3bb9bb3089375
```
Agora, quando olharmos para nossa transação, devemos ver algo novo: A linha ```bip125-replaceeable```, que sempre foi marcada como ```no``` antes, agora está marcada como ```yes```:
```
$ bitcoin-cli -named gettransaction txid=5b953a0bdfae0d11d20d195ea43ab7c31a5471d2385c258394f3bb9bb3089375
{
"amount": 0.00000000,
"fee": -0.00000141,
"confirmations": 0,
"trusted": true,
"txid": "5b953a0bdfae0d11d20d195ea43ab7c31a5471d2385c258394f3bb9bb3089375",
"walletconflicts": [
],
"time": 1592954399,
"timereceived": 1592954399,
"bip125-replaceable": "yes",
"details": [
],
"hex": "02000000000101fa364ad3cbdb08dd0b83aac009a42a9ed00594acd6883d2a466699996cd69d8b01000000000100000002ea1d000000000000160014d591091b8074a2375ed9985a9c4b18efecfd416501000000000000001600146c45d3afa8762086c4bd76d8a71ac7c976e1919602473044022077007dff4df9ce75430e3065c82321dca9f6bdcfd5812f8dc0daeb957d3dfd1602203a624d4e9720a06def613eeea67fbf13ce1fb6188d3b7e780ce6e40e859f275d0121038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec500000000"
}
```
O sinalizador ```bip125-replaceeable``` permanecerá como ```yes``` até que a transação receba confirmações. Nesse ponto, ela não é mais substituível.
> :book: ***Devo confiar nas transações que não possuem confirmações?*** Não, nunca. Isso era uma verdade antes do RBF e continua sendo depois do RBF. As transações devem receber confirmações antes de serem determinadas como confiáveis. Isto é especialmente verdadeiro se uma transação for marcada como ```bip125-replaceable```, porque ela pode muito bem ser... substituída.
> :information_source: **NOTA - SEQUÊNCIA:** Este é o primeiro uso do valor ```nSequence``` no Bitcoin. Podemos configurá-lo entre 1 e 0xffffffff-2 (4294967293) e habilitar o RBF, mas se não tivermos cuidado, poderemos bater de frente com o uso paralelo do ```nSequence``` que serve para _timelocks_ relativos. Sugerimos sempre configurá-lo como "1", que é o que o Bitcoin Core faz, mas a outra opção é configurá-lo com um valor entre 0xf0000000 (4026531840) e 0xffffffff-2 (4294967293). Configurá-lo como sendo "1" efetivamente torna os bloqueios de tempo relativos irrelevantes e configurá-lo para 0xf0000000 ou superior os desativa. Tudo isso é explicado posteriormente na seção [§11.3: Usando CSV nos Scripts](11_3_Using_CSV_in_Scripts.md). Por enquanto, basta escolhermos um dos valores não conflitantes para o ```nSequence```.
### Opcional: Sempre Habilite o RBF
Se preferirmos, podemos optar por _sempre_ habilitar o RBF. Podemos fazer isso executando nosso ```bitcoind``` com o comando ``` -walletrbf```. Depois de fazermos isso (e reiniciarmos nosso ```bitcoind```), todos os UTXOs devem ter um número de sequência inferior e as transações posteriores devem ser marcadas como ```bip125-replaceable```.
> :warning: **AVISO DE VERSÃO:** O sinalizador walletrbf requer o Bitcoin Core v.0.14.0 ou superior.
## Entendendo o Funcionamento do RBF
A funcionalidade RBF é baseada no [BIP 125](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki), que lista as seguintes regras para usá-lo:
> 1. As transações originais sinalizam a possibilidade de serem substituídas de maneira explicita ou por herança, conforme descrito na seção anterior.
Isso significa que o número de sequência deve ser definido para menos de 0xffffffff-1 (4294967294), ou o mesmo é verdadeiro para transações pai não confirmadas.
> 2. A transação de substituição paga uma taxa absolutamente mais alta do que a soma paga pelas transações originais.
> 3. A transação de substituição não contém nenhuma nova entrada não confirmada que não apareceu anteriormente na mempool. Entradas não confirmadas são entradas e saídas de gastos de transações atualmente não confirmadas.
> 4. A transação de substituição deve pagar por seu próprio tamanho, além do valor pago pelas transações originais, ou acima da taxa definida pela configuração de taxa de retransmissão mínima do node. Por exemplo, se a taxa mínima de retransmissão for 1 satoshi/byte e a transação de substituição for de 500 bytes no total, a substituição deverá pagar uma taxa pelo menos 500 satoshis superior à soma das transações originais.
> 5. O número de transações originais a serem substituídas e as transações filhas que serão removidas do mempool não deve exceder um total de 100 transações.
> :book: ***O que é um BIP?*** Um BIP é uma proposta de melhoria de Bitcoin (Bitcoin Improvement Proposal). É uma sugestão detalhada para uma mudança no código Bitcoin Core. Frequentemente, quando um BIP foi suficientemente discutido e atualizado, ele se tornará uma parte real do código do Bitcoin Core. Por exemplo, o BIP 125 foi implementado no Bitcoin Core 0.12.0.
A outra coisa a ser entendida sobre o RBF é que, para usá-lo, devemos gastar o dobro, reutilizando um ou mais UTXOs. Apenas enviar outra transação com um UTXO diferente para o mesmo destinatário não resolverá o problema (e provavelmente resultará em perda do saldo). Ao invés disso, devemos criar um conflito proposital, onde o mesmo UTXO é usado em duas transações diferentes.
Diante desse conflito, os mineradores saberão usar aquele com a taxa mais alta e serão incentivados a isso devido a taxa ser mais alta.
> :book: ***O que é um gasto duplo?*** Um gasto duplo ocorre quando alguém envia os mesmos fundos eletrônicos para duas pessoas diferentes (ou, para a mesma pessoa duas vezes, em duas transações diferentes). Este é um problema central para qualquer sistema de dinheiro digital. É resolvido no Bitcoin devido a blockchain imutável: Uma vez que uma transação seja suficientemente confirmada, nenhum minerador irá verificar transações que reutilizam o mesmo UTXO. No entanto, é possível fazer o gasto duplo _antes_ de uma transação ser confirmada. É por isso que sempre desejamos ter uma ou mais confirmações antes de finalizar uma transação. No caso do RBF, podemos propositalmente duplicar o gasto porque uma transação inicial ficou presa, e os mineradores aceitam o nosso gasto duplo se atendermos aos critérios específicos estabelecidos pelo BIP 125.
> :warning: **ATENÇÃO:** Algumas discussões anteriores sobre esta política sugeriram que o número ```nSequence``` também fosse aumentado. Na verdade, esse era o uso pretendido do ```nSequence``` em sua forma original. Isso _não_ faz parte da política publicada no BIP 125. Na verdade, aumentar o número da sequência, pode travar acidentalmente nossa transação com um _timelock_ relativo, a menos que usemos números de sequência no intervalo de 0xf0000000 (4026531840) a 0xffffffff-2 (4294967293) .
## Substituindo uma Transação no Modo Difícil: Manualmente
Para criar uma transação RBF manual, tudo o que precisamos fazer é criar uma transação bruta que: (1) Substitua uma transação bruta anterior onde o RBF foi habilitado e que não foi confirmada; (2) Reutilizar um ou mais dos mesmos UTXOs; (3) Aumentar as taxas e; (4) Pagar a taxa mínima de ambas as transações [que já podem ser atendidas no item (3)].
O exemplo a seguir apenas reutiliza as variáveis existentes, mas diminui o valor enviado para o endereço de troco, para aumentar a taxa de 0 BTC acidental da transação original para uma taxa de 0,01 BTC, excessivamente generosa, diga-se de passagem, nesta nova transação:
```
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "sequence": 1 } ]''' outputs='''{ "'$recipient'": 0.000075, "'$changeaddress'": 0.00000001 }''')
```
É claro que devemos assiná-la novamente e reenviá-la:
```
$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex | jq -r '.hex')
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
c6de60427b28d8ec8102e49771e5d0348fc3ef6a5bf02eb864ec745105a6951b
```
Agora podemos olhar para a nossa transação original e ver se ela tem ```walletconflicts```:
```
$ bitcoin-cli -named gettransaction txid=5b953a0bdfae0d11d20d195ea43ab7c31a5471d2385c258394f3bb9bb3089375
{
"amount": 0.00000000,
"fee": -0.00000141,
"confirmations": 0,
"trusted": false,
"txid": "5b953a0bdfae0d11d20d195ea43ab7c31a5471d2385c258394f3bb9bb3089375",
"walletconflicts": [
"c6de60427b28d8ec8102e49771e5d0348fc3ef6a5bf02eb864ec745105a6951b"
],
"time": 1592954399,
"timereceived": 1592954399,
"bip125-replaceable": "yes",
"details": [
],
"hex": "02000000000101fa364ad3cbdb08dd0b83aac009a42a9ed00594acd6883d2a466699996cd69d8b01000000000100000002ea1d000000000000160014d591091b8074a2375ed9985a9c4b18efecfd416501000000000000001600146c45d3afa8762086c4bd76d8a71ac7c976e1919602473044022077007dff4df9ce75430e3065c82321dca9f6bdcfd5812f8dc0daeb957d3dfd1602203a624d4e9720a06def613eeea67fbf13ce1fb6188d3b7e780ce6e40e859f275d0121038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec500000000"
}
```
Isso representa o fato de que duas transações diferentes estão tentando usar o mesmo UTXO.
Eventualmente, a transação com a taxa maior deve ser aceita:
```
$ bitcoin-cli -named gettransaction txid=c6de60427b28d8ec8102e49771e5d0348fc3ef6a5bf02eb864ec745105a6951b
{
"amount": 0.00000000,
"fee": -0.00000299,
"confirmations": 2,
"blockhash": "0000000000000055ac4b6578d7ffb83b0eccef383ca74500b00f59ddfaa1acab",
"blockheight": 1773266,
"blockindex": 9,
"blocktime": 1592955002,
"txid": "c6de60427b28d8ec8102e49771e5d0348fc3ef6a5bf02eb864ec745105a6951b",
"walletconflicts": [
"5b953a0bdfae0d11d20d195ea43ab7c31a5471d2385c258394f3bb9bb3089375"
],
"time": 1592954467,
"timereceived": 1592954467,
"bip125-replaceable": "no",
"details": [
],
"hex": "02000000000101fa364ad3cbdb08dd0b83aac009a42a9ed00594acd6883d2a466699996cd69d8b010000000001000000024c1d000000000000160014d591091b8074a2375ed9985a9c4b18efecfd416501000000000000001600146c45d3afa8762086c4bd76d8a71ac7c976e1919602473044022077dcdd98d85f6247450185c2b918a0f434d9b2e647330d741944ecae60d6ff790220424f85628cebe0ffe9fa11029b8240d08bdbfcc0c11f799483e63b437841b1cd0121038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec500000000"
}
```
Enquanto isso, a transação original com a taxa mais baixa começa a receber confirmações negativas, para mostrar a divergência com a blockchain:
```
$ bitcoin-cli -named gettransaction txid=5b953a0bdfae0d11d20d195ea43ab7c31a5471d2385c258394f3bb9bb3089375
{
"amount": 0.00000000,
"fee": -0.00000141,
"confirmations": -2,
"trusted": false,
"txid": "5b953a0bdfae0d11d20d195ea43ab7c31a5471d2385c258394f3bb9bb3089375",
"walletconflicts": [
"c6de60427b28d8ec8102e49771e5d0348fc3ef6a5bf02eb864ec745105a6951b"
],
"time": 1592954399,
"timereceived": 1592954399,
"bip125-replaceable": "yes",
"details": [
],
"hex": "02000000000101fa364ad3cbdb08dd0b83aac009a42a9ed00594acd6883d2a466699996cd69d8b01000000000100000002ea1d000000000000160014d591091b8074a2375ed9985a9c4b18efecfd416501000000000000001600146c45d3afa8762086c4bd76d8a71ac7c976e1919602473044022077007dff4df9ce75430e3065c82321dca9f6bdcfd5812f8dc0daeb957d3dfd1602203a624d4e9720a06def613eeea67fbf13ce1fb6188d3b7e780ce6e40e859f275d0121038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec500000000"
}
```
Nossos destinatários terão nosso saldo, e a transação original que foi falha acabará saindo do mempool.
## Substituindo uma Transação no Modo Fácil: Usando o bumpfee
As transações brutas são muito poderosas e podemos fazer muitas coisas interessantes combinando-as com o RBF. No entanto, às vezes _tudo_ o que desejamos é apenas liberar uma transação que está presa na mempool. Podemos fazer isso com um comando simples, o ```bumpfee```.
Por exemplo, para aumentar a taxa da transação ```4460175e8276d5a1935f6136e36868a0a3561532d44ddffb09b7cb878f76f927```, executaríamos o seguinte comando:
```
$ bitcoin-cli -named bumpfee txid=4460175e8276d5a1935f6136e36868a0a3561532d44ddffb09b7cb878f76f927
{
"txid": "75208c5c8cbd83081a0085cd050fc7a4064d87c7d73176ad9a7e3aee5e70095f",
"origfee": 0.00000000,
"fee": 0.00022600,
"errors": [
]
}
```
O resultado é a geração automática de uma nova transação que tem uma taxa determinada pelo arquivo ```bitcoin.conf```:
```
$ bitcoin-cli -named gettransaction txid=75208c5c8cbd83081a0085cd050fc7a4064d87c7d73176ad9a7e3aee5e70095f
{
"amount": -0.10000000,
"fee": -0.00022600,
"confirmations": 0,
"trusted": false,
"txid": "75208c5c8cbd83081a0085cd050fc7a4064d87c7d73176ad9a7e3aee5e70095f",
"walletconflicts": [
"4460175e8276d5a1935f6136e36868a0a3561532d44ddffb09b7cb878f76f927"
],
"time": 1491605676,
"timereceived": 1491605676,
"bip125-replaceable": "yes",
"replaces_txid": "4460175e8276d5a1935f6136e36868a0a3561532d44ddffb09b7cb878f76f927",
"details": [
{
"account": "",
"address": "n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi",
"category": "send",
"amount": -0.10000000,
"vout": 0,
"fee": -0.00022600,
"abandoned": false
}
],
"hex": "02000000014e843e22cb8ee522fbf4d8a0967a733685d2ad92697e63f52ce41bec8f7c8ac0020000006b48304502210094e54afafce093008172768d205d99ee2e9681b498326c077f0b6a845d9bbef702206d90256d5a2edee3cab1017b9b1c30b302530b0dd568e4af6f2d35380bbfaa280121029f39b2a19943fadbceb6697dbc859d4a53fcd3f9a8d2c8d523df2037e7c32a71010000000280969800000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac38f25c05000000001976a914c101d8c34de7b8d83b3f8d75416ffaea871d664988ac00000000"
}
```
> :aviso: **AVISO DE VERSÃO:** O comando ```bumpfee``` no RPC requer o Bitcoin Core v.0.14.0.
## Resumo: Reenviando uma Transação com RBF
Se uma transação ficar presa na mempool e não quisermos esperar que ela expire, e se habilitamos o RBF nela, podemos fazer um gasto duplo usando o RBF para criar uma transação de substituição (ou apenas usar o comando ```bumpfee```).
> :fire: ***Qual é o poder do RBF?*** Obviamente, o RBF é muito útil se criarmos uma transação com uma taxa muito baixa e precisamos acelerá-la. No entanto, a capacidade de substituir transações não confirmadas por transações atualizadas tem mais poder do que apenas isso (e é por isso que podemos querer continuar usando o RBF com transações brutas, mesmo após sabermos que existe o ```bumpfee```).
> Por exemplo, podemos enviar uma transação e, antes de ser confirmada, combiná-la com uma segunda transação. Isso permite que possamos comprimir várias transações em uma única, diminuindo as taxas totais. Também podemos oferecer benefícios à privacidade. Existem outras razões para usarmos o RBF, como por exemplo contratos inteligentes ou transferência de transações, conforme descrito na parte referente a [Perguntas frequentes sobre RBF de opt-in](https://bitcoincore.org/en/faq/optin_rbf/).
## O Que Vem Depois?
Vamos continuar "Controlando Transações no Bitcoin" na seção [§5.3: Financiando uma Transação com CPFP](05_3_Funding_a_Transaction_with_CPFP.md).

View File

@ -0,0 +1,127 @@
# 5.3: Financiando uma Transação com CPFP
Se nossa transação do Bitcoin travar e formos os _recebedores_, poderemos aumentar a velocidade usando o CPFP (Child-Pays-For-Parent). Esta é uma alternativa semelhante ao que a parte que _ envia_ o saldo pode fazer usando o RBF.
> :warning: **AVISO DE VERSÃO:** Esta é uma inovação do Bitcoin Core v0.13.0, o que novamente significa que a maioria das pessoas já deve estar utilizando-a.
## Entendendo o Funcionamento do CPFP
O RBF é possível caso você seja a parte que está enviando o saldo. O remetente errou e precisou aumentar a taxa, ou queria ser inteligente e combinar transações por diversos motivos. O RBF é um poderoso recurso voltado para o remetente. De certa forma, o CPFP é o oposto do RBF, pois dá poder ao destinatário que sabe que o dinheiro ainda não chegou e quer acelerar o processo. No entanto, também é um recurso muito mais simples, com aplicabilidade não tão ampla quanto a primeira.
Basicamente, a ideia do CPFP é que um destinatário tenha uma transação que não foi confirmada e deseja gastar o seu saldo. Portanto, ele inclui essa transação não confirmada em uma nova transação e paga uma taxa alta o suficiente para encorajar um minerador a incluir a transação original (pai) e a nova transação (filha) em um bloco. Como resultado, as duas transações são confirmadas e eliminadas da mempool simultaneamente.
Devemos observar que o CPFP não é um recurso novo no protocolo, assim como o RBF. É apenas um novo esquema de incentivo que pode ser usado para a seleção de transações pelos mineradores. Isso também significa que não é tão confiável quanto uma alteração feita pelo RBF: Pode haver motivos para que o filho não seja selecionado para ser colocado em um bloco e isso impedirá que o pai também seja colocado no bloco.
## Gastando UTXOs Não Confirmados
Financiar uma transação com o CPFP é um processo muito simples, usando os métodos com os quais já estamos familiarizados:
1. Encontre o ```txid``` e ```vout``` da transação não confirmada. Esta será a parte mais complicada, já que o ```bitcoin-cli``` geralmente tenta nos proteger de transações não confirmadas. O remetente pode enviar essas informações para nós, mesmo com apenas o ```txid```, devemos ser capazes de descobrir o ```vout``` em um explorador da blockchain;
Temos uma outra opção: Podemos usar o ```bitcoin-cli getrawmempool```, que pode ser usado para listar o conteúdo de toda a nossa mempool, onde estarão as transações não confirmadas. Podemos vasculhar várias transações se nossa mempool estiver cheia. Podemos obter mais informações sobre uma transação específica usando o comando ```bitcoin-cli getrawtransaction``` com o sinalizador verbose definido como ```true```:
```
$ bitcoin-cli getrawmempool
[
"95d51e813daeb9a861b2dcdddf1da8c198d06452bbbecfd827447881ff79e061"
]
$ bitcoin-cli getrawtransaction 95d51e813daeb9a861b2dcdddf1da8c198d06452bbbecfd827447881ff79e061 true
{
"txid": "95d51e813daeb9a861b2dcdddf1da8c198d06452bbbecfd827447881ff79e061",
"hash": "9729e47b8aee776112a82cec46df7638d112ca51856c53e238a9b1f7af3be4ce",
"version": 2,
"size": 247,
"vsize": 166,
"weight": 661,
"locktime": 1773277,
"vin": [
{
"txid": "7a0178472300247d423ac4a04ff9165fa5b944104f6d6f9ebc557c6d207e7524",
"vout": 0,
"scriptSig": {
"asm": "0014334f3a112df0f22e743ad97eec8195a00faa59a0",
"hex": "160014334f3a112df0f22e743ad97eec8195a00faa59a0"
},
"txinwitness": [
"304402207966aa87db340841d76d3c3596d8b4858e02aed1c02d87098dcedbc60721d8940220218aac9d728c9a485820b074804a8c5936fa3145ce68e24dcf477024b19e88ae01",
"03574b1328a5dc2d648498fc12523cdf708efd091c28722a422d122f8a0db8daa9"
],
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.01000000,
"n": 0,
"scriptPubKey": {
"asm": "OP_HASH160 f079f77f2ef0ef1187093379d128ec28d0b4bf76 OP_EQUAL",
"hex": "a914f079f77f2ef0ef1187093379d128ec28d0b4bf7687",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"2NFAkGiwnp8wvCodRBx3smJwxncuG3hndn5"
]
}
},
{
"value": 0.02598722,
"n": 1,
"scriptPubKey": {
"asm": "OP_HASH160 8799be12fb9eae6644659d95b9602ddfbb4b2aff OP_EQUAL",
"hex": "a9148799be12fb9eae6644659d95b9602ddfbb4b2aff87",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"2N5cDPPuCTtYq13oXw8RfpY9dHJW8sL64U2"
]
}
}
],
"hex": "0200000000010124757e206d7c55bc9e6f6d4f1044b9a55f16f94fa0c43a427d2400234778017a0000000017160014334f3a112df0f22e743ad97eec8195a00faa59a0feffffff0240420f000000000017a914f079f77f2ef0ef1187093379d128ec28d0b4bf768742a727000000000017a9148799be12fb9eae6644659d95b9602ddfbb4b2aff870247304402207966aa87db340841d76d3c3596d8b4858e02aed1c02d87098dcedbc60721d8940220218aac9d728c9a485820b074804a8c5936fa3145ce68e24dcf477024b19e88ae012103574b1328a5dc2d648498fc12523cdf708efd091c28722a422d122f8a0db8daa9dd0e1b00"
}
```
Vamos observar o vetor ```vout```. Assim, encontramos o objeto que corresponde ao nosso endereço. No nosso exemplo ele é o único. O valor ```n``` é o nosso ```vout```. Agora temos tudo que precisamos para criar uma nova transação CPFP.
```
$ utxo_txid=2NFAkGiwnp8wvCodRBx3smJwxncuG3hndn5
$ utxo_vout=0
$ recipient2=$(bitcoin-cli getrawchangeaddress)
```
2. Criar uma transação bruta usando a transação não confirmada como entrada;
3. Dobrar as taxas de transação (ou colocar mais do que isso);
Ao seguir essas etapas, tudo deve parecer igual ao que já fizemos, apesar de estarmos trabalhando com uma transação não confirmada. Para verificar se tudo está bem, podemos até olhar os resultados de nossa assinatura antes de salvarmos as informações em uma variável:
```
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient2'": 0.03597 }''')
$ bitcoin-cli -named signrawtransaction hexstring=$rawtxhex | jq -r '.hex'
02000000012b137ef780666ba214842ff6ea2c3a0b36711bcaba839c3710f763e3d9687fed000000006a473044022003ca1f6797d781ef121ba7c2d1d41d763a815e9dad52aa8bc5ea61e4d521f68e022036b992e8e6bf2c44748219ca6e0056a88e8250f6fd0794dc69f79a2e8993671601210317b163ab8c8862e09c71767112b828abd3852e315441893fa0f535de4fa39b8dffffffff01905abd07000000001976a91450b1d90a130c4f3f1e5fbfa7320fd36b7265db0488ac00000000
$ signedtx=$(bitcoin-cli -named signrawtransaction hexstring=$rawtxhex | jq -r '.hex')
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
6a184a2f07fa30189f4831d6f041d52653a103b3883d2bec2f79187331fd7f0e
```
4. Cruzar os dedos não é necessário. Verificamos que nossos dados estão corretos. Deste ponto em diante, as coisas estão fora de nosso controle.
Nossas transações podem ser processadas rapidamente, ou não. Tudo depende se os mineradores que estão gerando aleatoriamente os blocos possuem o patch CPFP ou não. Apesar disso, fizemos tudo o que pudemos.
E isso realmente é tudo o que podemos fazer.
### Atenção aos Nuances
Embora o CPFP seja geralmente descrito como sendo um destinatário que usa uma nova transação para pagar por uma antiga que não foi confirmada, existem alguns nuances.
A parte que está _enviando_ poderia usar o CPFP para liberar uma transação se recebesse algum troco. Ele apenas usaria essa mudança como uma entrada, e o uso resultante do CPFP liberaria toda a transação. Lembre-se de que ele poderia fazer algo melhor se usasse o RBF, desde que estivesse habilitado, pois as taxas totais seriam menores.
A parte que está _recebendo_ pode usar o CPFP mesmo se não estiver planejando gastar o dinheiro imediatamente, por exemplo, se estiver preocupado que os fundos possam não ser reenviados se a transação expirar. Nesse caso, ele apenas cria uma transação secundária que envia todo o dinheiro (menos a taxa de transação) para um endereço de troco. Isso é o que fizemos no nosso exemplo.
## Resumo: Financiando uma Transação com CPFP
Podemos aproveitar os incentivos do CPFP para liberar fundos que nos foram enviados, mas que não foram confirmados. Basta usar a transação não confirmada como sendo um UTXO e pagar uma taxa de transação acima da média.
> :fire: ***Qual é o poder do CPFP?*** O seu uso é apenas para liberar fundos quando formos os recebedores dos fundos e o remetente não quer ajudar por qualquer que seja o motivo. Ele não tem as mesmas habilidades que o RBF, mas é uma maneira alternativa de exercer controle sobre uma transação depois que ela foi colocada na mempool, mas antes de ser confirmada em um bloco.
## O Que Vem Depois?
Vamos avançar para o [Capítulo 6: Expandindo Transações no Bitcoin com Multisigs](06_0_Expanding_Bitcoin_Transactions_Multisigs.md).

View File

@ -0,0 +1,19 @@
# Capítulo 6: Expandindo Transações no Bitcoin com Multisigs
Transações básicas no Bitcoin: (1) enviam fundos; (2) para um único destinatário P2PKH ou SegWit; (3) de uma única máquina; (4) imediatamente. No entanto, todas as quatro partes desta definição podem ser expandidas usando transações mais complexas no Bitcoin. Este primeiro capítulo sobre "Expansão" mostra como variar os pontos (2) e (3) enviando saldos para um endereço que representa vários destinatários (ou, pelo menos, vários assinantes).
## Objetivos deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Criar endereços de Bitcoin multi-assinatura (multisig) usando os fundamentos do Bitcoin;
* Criar endereços de Bitcoin multi-assinatura (multisig) usando mecanismos mais fáceis.
Os objetivos secundários do capítulo incluem a capacidade de:
* Entender como gastar fundos enviados para um multisig;
* Planejar para obter o máximo do poder dos multisigs.
## Tabela de Conteúdo
* [Seção 1: Enviando uma Transação com Multsig](06_1_Sending_a_Transaction_to_a_Multisig.md)
* [Seção 2: Gastando uma Transação com Multsig](06_2_Spending_a_Transaction_to_a_Multisig.md)
* [Seção 3: Enviando & Gastando um Multisig Automatizado](06_3_Sending_an_Automated_Multisig.md)

View File

@ -0,0 +1,207 @@
# 6.1: Enviando uma Transação com Multisig
A primeira maneira de variar a forma como enviamos uma transação básica é usando um multisig. Isso nos dá a capacidade de exigir que várias pessoas (ou, ao menos, várias chaves privadas) autorizem o uso dos fundos.
## Entendendo como Funcionam os Multisigs
Em uma transação P2PKH ou SegWit padrão, os bitcoins são enviados para um endereço baseado na chave pública, o que significa que a chave privada relacionada é necessária para desbloquear a transação, resolvendo o quebra-cabeça criptográfico e permitindo que reutilizemos o saldo. Mas e se pudéssemos bloquear uma transação com _múltiplas_ chaves privadas? Isso efetivamente permitiria que os fundos fossem enviados a um grupo de pessoas, onde todas teriam que concordar em reutilizar o saldo.
> :book: ***O que é uma multi-assinatura?*** Uma multi-assinatura é uma metodologia que permite que mais de uma pessoa crie uma assinatura digital em conjunto. É uma técnica geral para o uso criptográfico de chaves que vai muito além do Bitcoin.
Tecnicamente, um quebra-cabeça criptográfico com várias assinaturas é criado pelo Bitcoin usando o comando OP_CHECKMULTISIG e, normalmente, é encapsulado em um endereço P2SH. A seção [§10.4: Programando um Multisig](10_4_Scripting_a_Multisig.md) irá detalhar como isso funciona com mais precisão. Por enquanto, tudo que precisamos saber é que podemos usar o comando ```bitcoin-cli``` para criar endereços multi-assinatura. Os fundos podem ser enviados para esses endereços como qualquer endereço P2PKH ou Segwit normal, mas várias chaves privadas serão necessárias para que o saldo seja resgatado.
> :book: ***O que é uma transação multisig?*** Uma transação multisig é uma transação no Bitcoin enviada para um endereço com várias assinaturas, exigindo assim que certas pessoas do grupo multi-assinatura precisem assinar a transação para poder reutilizar o saldo.
Multisigs simples exigem que todos no grupo assinem o UTXO quando for gasto. No entanto, há mais complexidade possível. Multisigs são geralmente descritos como sendo "m de n". Isso significa que a transação está trancada com um grupo de chaves "n", mas apenas "m" delas são necessárias para desbloquear a transação.
> :book: ***O que é um multisg m-de-n?*** Em um multisig, "m" assinaturas de um grupo de "n" são necessárias para formar a assinatura, onde "m ≤ n".
## Criando um Endereço Multisig
Para trancar um UTXO com várias chaves privadas, devemos primeiro criar um endereço multi-assinatura. Os exemplos usados aqui mostram a criação (e uso) de um multisig 2-de-2.
### Criando os Endereços
Para criar um endereço multisig, devemos primeiro preparar os endereços que o multisig irá combinar. A prática recomendada sugere que sempre criemos novos endereços. Isso significa que cada participante irá executar o comando ```getnewaddress``` em sua própria máquina:
```
machine1$ address1=$(bitcoin-cli getnewaddress)
```
E:
```
machine2$ address2=$(bitcoin-cli getnewaddress)
```
Posteriormente, um dos destinatários (ou talvez algum terceiro) precisará combinar ambos endereços.
#### Coletando Chaves Públicas
No entanto, não podemos criar um multisig com os endereços, pois esses são os hashes das chaves públicas: Ao invés disso, precisamos das próprias chaves públicas.
Esta informação está disponível facilmente com o comando ```getaddressinfo```.
Na máquina remota, que assumimos aqui que é ```machine2```, podemos obter as informações em uma lista.
```
machine2$ bitcoin-cli -named getaddressinfo address=$address2
{
"address": "tb1qr2tkjh8rs9xn5xaktf5phct0wxqufplawrfd9q",
"scriptPubKey": "00141a97695ce3814d3a1bb65a681be16f7181c487fd",
"ismine": true,
"solvable": true,
"desc": "wpkh([fe6f2292/0'/0'/1']02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3)#zc64l8dw",
"iswatchonly": false,
"isscript": false,
"iswitness": true,
"witness_version": 0,
"witness_program": "1a97695ce3814d3a1bb65a681be16f7181c487fd",
"pubkey": "02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3",
"ischange": false,
"timestamp": 1592957904,
"hdkeypath": "m/0'/0'/1'",
"hdseedid": "1dc70547f2b80e9bb5fde5f34fb3d85f8d8d1dab",
"hdmasterfingerprint": "fe6f2292",
"labels": [
""
]
}
```
O endereço ```pubkey``` (` 02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3`) é o que precisamos. Vamos copiá-lo para nossa máquina local por qualquer meio que acharmos mais eficiente e _que seja menos sujeito a erros_.
Este processo precisa ser realizado para _cada_ endereço de uma máquina diferente daquela onde o multisig está sendo construído. Obviamente, se algum terceiro estiver criando o endereço, precisaremos fazer isso para cada endereço.
> :warning: **ATENÇÃO:** O uso de hashes de chave pública pelo Bitcoin como endereços, ao invés de chaves públicas, na verdade representa uma camada adicional de segurança. Portanto, o envio de uma chave pública aumenta ligeiramente a vulnerabilidade do endereço associado, devido a alguma possibilidade do comprometimento da curva elíptica em um futuro distante. Não devemos nos preocupar em termos que enviar ocasionalmente uma chave pública para um uso como esse, mas devemos estar cientes de que os hashes de chave pública representam segurança e, portanto, as chaves públicas reais não devem ser enviadas de qualquer jeito para qualquer pessoa.
Se um dos endereços foi criado em nossa máquina local, que assumimos aqui que seja ```machine1```, podemos simplesmente colocar o endereço ```pubkey``` em uma nova variável.
```
machine1$ pubkey1=$(bitcoin-cli -named getaddressinfo address=$address1 | jq -r '.pubkey')
```
### Criando o Endereço
Um multisig agora pode ser criado com o comando ```createmultisig```:
```
machine1$ bitcoin-cli -named createmultisig nrequired=2 keys='''["'$pubkey1'","02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3"]'''
{
"address": "2N8MytPW2ih27LctLjn6LfLFZZb1PFSsqBr",
"redeemScript": "522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae",
"descriptor": "sh(multi(2,02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191,02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3))#0pazcr4y"
}
```
> :warning: **AVISO DE VERSÃO:** Algumas versões do ```createmultisig``` permitem a entrada de chaves públicas ou endereços, algumas requerem apenas as chaves públicas. Atualmente, ambas parecem funcionar.
Ao criar o endereço multisig, listamos quantas assinaturas são necessárias com o argumento ```nrequired``` (que é o "m" em um multisig "m-de-n"), então listamos o conjunto total de assinaturas possíveis com a argumento ```keys``` (que é o "n"). Observe que as entradas ```keys``` provavelmente vieram de lugares diferentes. Nesse caso, incluímos ```$pubkey1``` da máquina local e ```02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3``` de uma máquina remota.
> :information_source: **NOTA M-DE-N VS N-DE-N:** Este exemplo mostra a criação de um multisig simples 2-de-2 . Se quisermos criar uma assinatura m-de-n onde "m < n", precisamos apenas ajustar o campo ```nrequired``` e/ou o número de assinaturas ```keys``` no objeto JSON. Para um multisig 1-de-2, seria definido como ```nrequired = 1``` e também listaria duas chaves, enquanto para um multisig 2-de-3, seria necessário um ```nrequired = 2```, mas adicionaria mais uma chave pública à lista de ```keys```.
Quando usado corretamente, o ```createmultisig``` retorna três resultados, todos criticamente importantes.
O _endereço_ é o que iremos distribuir para as pessoas que desejam enviar os fundos. Podemos notar que ele tem um novo prefixo ```2```, exatamente como os endereços P2SH-SegWit. Isso porque, como eles, o comando ```createmultisig``` está na verdade criando um tipo de endereço totalmente novo chamado endereço P2SH. Ele funciona exatamente como um endereço P2PKH padrão para envio de fundos, mas como este foi criado para exigir vários endereços, precisaremos trabalhar um pouco mais para utilizá-los.
> :link: **TESTNET vs MAINNET:** Na testenet, o prefixo para endereços P2SH é ```2```, enquanto na Mainnet é ```3```.
O _redeemScript_ é o que precisaremos para resgatar os fundos (junto com as chaves privadas de "m" dos "n" endereços). Este script é outro recurso especial dos endereços P2SH e será explicado com mais detalhes na seção [§10.3: Rodando um Script no Bitcoin com P2SH](10_3_Running_a_Bitcoin_Script_with_P2SH.md). Por enquanto, precisamos apenas saber que alguns dados são necessários para podemos gastar nosso dinheiro.
O _descritor_ é a descrição padronizada para um endereço que encontramos na seção [§3.5: Compreendendo o Descritor](03_5_Understanding_the_Descriptor.md). Ele fornece uma maneira de importar esse endereço de volta para a outra máquina, usando o RPC ```importmulti```.
> :book: ***O que é um endereço P2SH?*** O P2SH significa Pay-To-Script-Hash. É um tipo de destinatário diferente de um endereço P2PKH padrão ou mesmo de um Bech32, usado para fundos cujo resgate é baseado em scripts de Bitcoin mais complexos. O ```bitcoin-cli``` usa o encapsulamento P2SH para ajudar a padronizar e simplificar os multisigs como "multisigs P2SH", assim como P2SH-SegWit estava usando o P2SH para padronizar os endereços SegWit e torná-los totalmente compatíveis com as versões antigas.
> :warning: **ATENÇÃO:** endereços P2SH multisig, como os criados pelo ```bitcoin-cli```, têm um limite para "m" e "n" nos multisigs com base no tamanho máximo do script de resgate, que atualmente é de 520 bytes. Praticamente, não vamos chegar a isso, a menos que estejamos nos excedendo em algo.
### Salvando Nosso Trabalho
Aqui está uma informação importante: nada sobre nosso multisig é salvo em nossa carteira usando essas técnicas básicas. Para resgatar o saldo enviado para este endereço multisig no futuro, precisaremos reter duas informações cruciais:
* Uma lista dos endereços Bitcoin usados no multisig, e;
* A saída ```redeemScript``` criada pelo comando ```createmultsig```.
Tecnicamente, o ```redeemScript``` pode ser recriado executando novamente o ```createmultisig``` com a lista completa de chaves públicas _na mesma ordem_ e com a contagem m-de-n correta. Mas, é melhor agarrar-se a ela e evitar qualquer tipo de estresse futuro.
### Observe a Ordem
Aqui está mais uma coisa que devemos tomar muito cuidado: _a ordem importa_. A ordem das chaves usadas para criar um multisig cria um hash único, ou seja, se colocarmos as chaves em uma ordem diferente, elas irão produzir um endereço diferente, conforme mostrado abaixo:
```
$ bitcoin-cli -named createmultisig nrequired=2 keys='''["'$pubkey1'","'$pubkey2'"]'''
{
"address": "2NFBQvz57UzKWDr2Vx5D667epVZifjGixkm",
"redeemScript": "52210342b306e410283065ffed38c3139a9bb8805b9f9fa6c16386e7ea96b1ba54da0321039cd6842869c1bfec13cfdbb7d8285bc4c501d413e6633e3ff75d9f13424d99b352ae",
"descriptor": "sh(multi(2,0342b306e410283065ffed38c3139a9bb8805b9f9fa6c16386e7ea96b1ba54da03,039cd6842869c1bfec13cfdbb7d8285bc4c501d413e6633e3ff75d9f13424d99b3))#8l6hvjsk"
}
standup@btctest20:~$ bitcoin-cli -named createmultisig nrequired=2 keys='''["'$pubkey2'","'$pubkey1'"]'''
{
"address": "2N5bC4Yc5Pqept1y8nPRqvWmFSejkVeRb1k",
"redeemScript": "5221039cd6842869c1bfec13cfdbb7d8285bc4c501d413e6633e3ff75d9f13424d99b3210342b306e410283065ffed38c3139a9bb8805b9f9fa6c16386e7ea96b1ba54da0352ae",
"descriptor": "sh(multi(2,039cd6842869c1bfec13cfdbb7d8285bc4c501d413e6633e3ff75d9f13424d99b3,0342b306e410283065ffed38c3139a9bb8805b9f9fa6c16386e7ea96b1ba54da03))#audl88kg"
}
```
Mais notavelmente, cada ordem cria um _redeemScript_ diferente. Isso significa que se usamos essas técnicas básicas e não salvarmos o redemScript conforme as instruções, teremos que percorrer um número cada vez maior de variações para encontrar a correta quando tentarmos gastar os fundos!
O [BIP67](https://github.com/bitcoin/bips/blob/master/bip-0067.mediawiki) sugere uma maneira de ordenar lexicograficamente as chaves, de modo que sempre gerem as mesmas multisigs. A ColdCard e a Electrum estão entre as carteiras que já possuem suporte a isso. Claro, isso pode causar problemas por si só se não soubermos se um endereço multisig foi criado com chaves classificadas ou não classificadas. Mais uma vez, os [descritores](03_5_Understanding_the_Descriptor.md) vêm ao nosso resgate. Se um multisig não for classificado, ele será construído com a função ```multi```, e se for classificado, será construído com a função ```sortedmulti```.
Se olharmos o ```desc``` do multisig que criamos acima, veremos que o Bitcoin Core atualmente não classifica os multisigs:
```
"descriptor": "sh(multi(2,02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191,02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3))#0pazcr4y"
```
Porém, se ele importa um endereço do tipo ```sortedmulti```, ele fará o processo correto, que é o ponto principal dos descritores!
> :warning: **AVISO DE VERSÃO:** O Bitcoin Core só entende a função do descritor ```sortedmulti``` após a versão 0.20.0. Podemos tentar acessar o descritor em uma versão anterior do Bitcoin Core e obteremos um erro como ```A function is needed within P2WSH```.
## Enviando para um Endereço Multisig
Se tivermos um multisig em um formato P2SH conveniente, como o gerado pelo ```bitcoin-cli```, podemos enviar como um endereço normal.
```
$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
$ recipient="2N8MytPW2ih27LctLjn6LfLFZZb1PFSsqBr"
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.000065}''')
$ bitcoin-cli -named decoderawtransaction hexstring=$rawtxhex
{
"txid": "b164388854f9701051809eed166d9f6cedba92327e4296bf8a265a5da94f6521",
"hash": "b164388854f9701051809eed166d9f6cedba92327e4296bf8a265a5da94f6521",
"version": 2,
"size": 83,
"vsize": 83,
"weight": 332,
"locktime": 0,
"vin": [
{
"txid": "c6de60427b28d8ec8102e49771e5d0348fc3ef6a5bf02eb864ec745105a6951b",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00006500,
"n": 0,
"scriptPubKey": {
"asm": "OP_HASH160 a5d106eb8ee51b23cf60d8bd98bc285695f233f3 OP_EQUAL",
"hex": "a914a5d106eb8ee51b23cf60d8bd98bc285695f233f387",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"2N8MytPW2ih27LctLjn6LfLFZZb1PFSsqBr"
]
}
}
]
}
$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex | jq -r '.hex')
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
b164388854f9701051809eed166d9f6cedba92327e4296bf8a265a5da94f6521
```
Como podemos ver, não houve nada de incomum na criação da transação e ela parece normal, embora com um endereço com um prefixo diferente do normal (```2N8MytPW2ih27LctLjn6LfLFZZb1PFSsqBr```). Sem surpresa, como também não vimos diferença quando enviamos para endereços Bech32 pela primeira vez na seção [§4.6](04_6_Creating_a_Segwit_Transaction.md).
## Resumo: Enviando uma Transação com Multisig
Os endereços multisig trancam os fundos usando várias chaves privadas, possivelmente exigindo todas essas chaves privadas para resgate e, possivelmente, exigindo apenas algumas do conjunto. Eles são fáceis de serem criados com o ```bitcoin-cli``` e são simples para serem enviados. Essa facilidade se deve em grande parte ao uso invisível de endereços P2SH (Pay-To-Script-Hash), um tópico extenso que já falamos duas vezes, com endereços P2SH-SegWit e agora com os multisigs, e um outro que receberá mais atenção no futuro.
> :fire: ***Qual é o poder das multi-assinaturas?*** As multi-assinaturas permitem a modelagem de uma variedade de arranjos financeiros, como corporações, parcerias, comitês e outros grupos. Um multisig 1-de-2 pode ser a conta bancária conjunta de um casal, enquanto um multisig 2-de-2 pode ser usado para grandes despesas por uma parceria de responsabilidade limitada. Os multisigs também constituem uma das bases dos Smart Contracts. Por exemplo, um negócio imobiliário pode ser fechado com um multisig 2-de-3, onde as assinaturas são enviadas pelo comprador, pelo vendedor e por um agente de custódia. Depois que o agente de custódia concorda que todas as condições foram atendidas, ele libera os fundos para o vendedor, ou, alternativamente, o comprador e o vendedor podem liberar os fundos em conjunto.
## O Que Vem Depois?
Vamos continuar "Expandindo Transações no Bitcoin com Multisigs" na seção [§6.2: Gastando uma Transação com Multisig](06_2_Spending_a_Transaction_to_a_Multisig.md).

View File

@ -0,0 +1,229 @@
# 6.2: Gastando uma Transação com Multsig
A maneira clássica e complexa de gastar fundos enviados para um endereço com várias assinaturas usando o ```bitcoin-cli``` requer que suemos bastante a camisa.
## Encontrando os Fundos
Para começar, precisamos encontrar nossos fundos. Nosso computador não sabe procurá-los, porque não estão associados a nenhum endereço da nossa carteira. Podemos alertar o ```bitcoind``` para fazer isso usando o comando ```importaddress```:
```
$ bitcoin-cli -named importaddress address=2NAGfA4nW6nrZkD5je8tSiAcYB9xL2xYMCz
```
Se temos um node prunado (e provavelmente temos), ao invés desse jeito, precisaremos dizer não para verificar novamente:
```
$ bitcoin-cli -named importaddress address=2NAGfA4nW6nrZkD5je8tSiAcYB9xL2xYMCz rescan="false"
```
Se preferirmos, podemos importar o endereço usando nosso descritor (e esta é geralmente a melhor resposta, porque é mais padronizada):
```
$ bitcoin-cli importmulti '[{"desc": "sh(multi(2,02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191,02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3))#0pazcr4y", "timestamp": "now", "watchonly": true}]'
[
{
"success": true
}
]
```
Depois, os fundos devem aparecer quando usarmos o comando ```listunspent```, porém, ainda não podemos gastar facilmente. Na verdade, nossa carteira pode alegar que não podemos gastá-los de forma alguma!
Se por algum motivo não puder incorporar o endereço da nossa carteira, podemos usar o comando ```gettransaction``` para obtermos mais informações (ou olharmos em um block explorer).
```
$ bitcoin-cli -named gettransaction txid=b164388854f9701051809eed166d9f6cedba92327e4296bf8a265a5da94f6521 verbose=true
{
"amount": -0.00006500,
"fee": -0.00001000,
"confirmations": 3,
"blockhash": "0000000000000165b5f602920088a7e36b11214161d6aaebf5229e3ed4f10adc",
"blockheight": 1773282,
"blockindex": 9,
"blocktime": 1592959320,
"txid": "b164388854f9701051809eed166d9f6cedba92327e4296bf8a265a5da94f6521",
"walletconflicts": [
],
"time": 1592958753,
"timereceived": 1592958753,
"bip125-replaceable": "no",
"details": [
{
"address": "2N8MytPW2ih27LctLjn6LfLFZZb1PFSsqBr",
"category": "send",
"amount": -0.00006500,
"vout": 0,
"fee": -0.00001000,
"abandoned": false
}
],
"hex": "020000000001011b95a6055174ec64b82ef05b6aefc38f34d0e57197e40281ecd8287b4260dec60000000000ffffffff01641900000000000017a914a5d106eb8ee51b23cf60d8bd98bc285695f233f38702473044022070275f81ac4129e1d167ef7e700739f2899ea4c7f1adef3a4da29436f14fb97e02207310d4ec449eba49f0fa404ae45b9c82431d883490c7a0ed882ad0b5d7a623d0012102883bb5463e37d55252d8b3d5c2141b007b37c8a7db6211f75c955acc5ea325eb00000000",
"decoded": {
"txid": "b164388854f9701051809eed166d9f6cedba92327e4296bf8a265a5da94f6521",
"hash": "bdf4e3bc5d354a5dfa5528f172480976321d989d7e5806ac14f1fe9b0b1c093a",
"version": 2,
"size": 192,
"vsize": 111,
"weight": 441,
"locktime": 0,
"vin": [
{
"txid": "c6de60427b28d8ec8102e49771e5d0348fc3ef6a5bf02eb864ec745105a6951b",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"txinwitness": [
"3044022070275f81ac4129e1d167ef7e700739f2899ea4c7f1adef3a4da29436f14fb97e02207310d4ec449eba49f0fa404ae45b9c82431d883490c7a0ed882ad0b5d7a623d001",
"02883bb5463e37d55252d8b3d5c2141b007b37c8a7db6211f75c955acc5ea325eb"
],
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00006500,
"n": 0,
"scriptPubKey": {
"asm": "OP_HASH160 a5d106eb8ee51b23cf60d8bd98bc285695f233f3 OP_EQUAL",
"hex": "a914a5d106eb8ee51b23cf60d8bd98bc285695f233f387",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"2N8MytPW2ih27LctLjn6LfLFZZb1PFSsqBr"
]
}
}
]
}
}
```
## Configurando as Nossas Variáveis
Quando estivermos prontos para gastar os fundos recebidos por um endereço multisig, precisaremos coletar _muitos_ dados: muito mais do que precisamos quando fazemos uma transação usando um UTXO de um P2PKH normal ou SegWit. Isso ocorre em parte porque as informações sobre o endereço multisig não estão em nossa posse e em parte porque estamos gastando dinheiro que foi enviado para um endereço P2SH (Pay-To-Script-Hash) e isso é muito mais exigente.
No total, precisaremos coletar três coisas: informações estendidas sobre o UTXO; o redemScript e; todas as chaves privadas envolvidas. Obviamente, também iremos precisar de um novo endereço de destinatário. As chaves privadas precisam aguardar a etapa de assinatura, mas tudo pode ser feito agora.
### Acessando as Informações do UTXO
Para começar, vamos pegar o ```txid``` e o ```vout``` para a transação que desejamos gastar, como de costume. Nesse caso, os dados foram recuperados das informações ```gettransaction``` acima:
```
$ utxo_txid=b164388854f9701051809eed166d9f6cedba92327e4296bf8a265a5da94f6521
$ utxo_vout=0
```
No entanto, precisamos também acessar um terceiro pedaço de informação sobre o UTXO, nosso ```scriptPubKey```/```hex```, que é o script que travou a transação. Novamente, podemos fazer isso observando os detalhes da transação:
```
$ utxo_spk=a914a5d106eb8ee51b23cf60d8bd98bc285695f233f387
```
### Gravando o Script de Resgate
Felizmente, salvamos nosso ```redeemScript```. Agora devemos registrá-lo em uma variável.
O valor foi extraído da criação de endereço na seção anterior.
```
redeem_script="522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae"
```
### Decidindo o Destinatário
Vamos apenas enviar o dinheiro de volta para nós mesmos. Isso é útil porque libera os fundos do multisig, convertendo-os em uma transação P2PKH normal que pode ser posteriormente confirmada por uma única chave privada:
```
$ recipient=$(bitcoin-cli getrawchangeaddress)
```
## Criando Nossa Transação
Agora podemos criar nossa transação. Essa parte é parecida com as transações normais.
```
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.00005}''')
$ echo $rawtxhex
020000000121654fa95d5a268abf96427e3292baed6c9f6d16ed9e80511070f954883864b10000000000ffffffff0188130000000000001600142c48d3401f6abed74f52df3f795c644b4398844600000000
```
## Assinando Nossa Transação
Agora estamos prontos para assinar a transação. Este é um processo de várias etapas porque precisaremos fazer em várias máquinas, cada uma das quais contribuirá com suas próprias chaves privadas.
### Carregando a Primeira Chave Privada
Como essa transação não está fazendo uso total da nossa carteira, precisaremos acessar diretamente as chaves privadas. Começando com a ```máquina1```, onde devemos recuperar qualquer uma das chaves privadas do usuário que estavam envolvidas no multisig:
```
machine1$ bitcoin-cli -named dumpprivkey address=$address1
cNPhhGjatADfhLD5gLfrR2JZKDE99Mn26NCbERsvnr24B3PcSbtR
```
> :warning: **ATENÇÃO:** Acessar diretamente as chaves privadas do shell é um comportamento muito perigoso e deve ser feito com extremo cuidado se estivermos usando dinheiro de verdade. No mínimo, é importante não salvar as informações em uma variável que possa ser acessada pela nossa máquina. Remover o histórico do shell é outro grande passo. No máximo, podemos evitar de fazer isso.
### Fazendo Nossa Primeira Assinatura
Agora podemos fazer nossa primeira assinatura com o comando ```signrawtransactionwithkey```. É aqui que as coisas ficam diferentes: precisaremos treinar o comando sobre como assinar. Podemos fazer isso adicionando as seguintes informações novas:
* Incluir um argumento ```prevtxs``` que tenha o ```txid```, o ```vout```, o ```scriptPubKey``` e o ```redeemScript``` que gravamos, cada um deles um par individual do valor-chave no objeto JSON.
* Incluir um argumento ```privkeys``` que lista as chaves privadas que pegamos nesta máquina.
```
machine1$ bitcoin-cli -named signrawtransactionwithkey hexstring=$rawtxhex prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cNPhhGjatADfhLD5gLfrR2JZKDE99Mn26NCbERsvnr24B3PcSbtR"]'
{
"hex": "020000000121654fa95d5a268abf96427e3292baed6c9f6d16ed9e80511070f954883864b100000000920047304402201c97b48215f261055e41b765ab025e77a849b349698ed742b305f2c845c69b3f022013a5142ef61db1ff425fbdcdeb3ea370aaff5265eee0956cff9aa97ad9a357e3010047522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352aeffffffff0188130000000000001600142c48d3401f6abed74f52df3f795c644b4398844600000000",
"complete": false,
"errors": [
{
"txid": "b164388854f9701051809eed166d9f6cedba92327e4296bf8a265a5da94f6521",
"vout": 0,
"witness": [
],
"scriptSig": "0047304402201c97b48215f261055e41b765ab025e77a849b349698ed742b305f2c845c69b3f022013a5142ef61db1ff425fbdcdeb3ea370aaff5265eee0956cff9aa97ad9a357e3010047522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae",
"sequence": 4294967295,
"error": "CHECK(MULTI)SIG failing with non-zero signature (possibly need more signatures)"
}
]
}
```
Isso produz erros assustadores e mostra um status de ```failing```. Tudo bem. Podemos ver que a assinatura foi parcialmente bem-sucedida porque o ```hex``` ficou mais longo. Embora a transação tenha sido parcialmente assinada, ela não foi concluída porque precisa de mais assinaturas.
### Repetindo para os Outros Assinantes
Agora podemos passar a transação adiante, para ser assinada novamente por outros exigidos pelo multisig. Eles fazem isso executando o mesmo comando de assinatura que fizemos, porém: (1) com o ```hex``` maior que produzimos anteriormente (```bitcoin-cli -named signrawtransactionwithkey hexstring = $ rawtxhex prevtxs = '' '[{"txid": " '$ utxo_txid'", "vout": '$ utxo_vout', "scriptPubKey": " '$ utxo_spk'", "redeemScript": " '$ redeem_script'"}] '' 'privkeys =' [ "cMgb3KM8hPATCtgMKarKMiFesLft6eEw3DY6BB8d97fkeXeqQagw"] '| jq -r'. | .hex'```) e; (2) com sua própria chave privada.
> :information_source: **NOTA - M-DE-N VS N-DE-N:** Obviamente, se tivermos uma assinatura N de N (como a multisig 2-de-2 do exemplo), todas as partes precisarão assinar, mas se tivermos uma multi-assinatura m-de-n onde "m < n", a assinatura estará completa quando apenas alguns ("m") tiverem assinado.
Para fazer isso, primeiro eles acessam suas chaves privadas:
```
machine2$ bitcoin-cli -named dumpprivkey address=$address2
cVhqpKhx2jgfLUWmyR22JnichoctJCHPtPERm11a2yxnVFKWEKyz
```
Depois, assinam o novo ```hex``` usando os mesmos valores ```prevtxs```:
```
machine1$ bitcoin-cli -named signrawtransactionwithkey hexstring=020000000121654fa95d5a268abf96427e3292baed6c9f6d16ed9e80511070f954883864b100000000920047304402201c97b48215f261055e41b765ab025e77a849b349698ed742b305f2c845c69b3f022013a5142ef61db1ff425fbdcdeb3ea370aaff5265eee0956cff9aa97ad9a357e3010047522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352aeffffffff0188130000000000001600142c48d3401f6abed74f52df3f795c644b4398844600000000 prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cVhqpKhx2jgfLUWmyR22JnichoctJCHPtPERm11a2yxnVFKWEKyz"]'
{
"hex": "020000000121654fa95d5a268abf96427e3292baed6c9f6d16ed9e80511070f954883864b100000000d90047304402201c97b48215f261055e41b765ab025e77a849b349698ed742b305f2c845c69b3f022013a5142ef61db1ff425fbdcdeb3ea370aaff5265eee0956cff9aa97ad9a357e301473044022000a402ec4549a65799688dd531d7b18b03c6379416cc8c29b92011987084e9f402205470e24781509c70e2410aaa6d827aa133d6df2c578e96a496b885584fb039200147522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352aeffffffff0188130000000000001600142c48d3401f6abed74f52df3f795c644b4398844600000000",
"complete": true
}
```
Por fim, podem precisar enviar uma ```hexstring``` ainda mais longa que eles tenham produzido para assinantes adicionais.
Mas, neste caso, podemos ver que a assinatura está `complete`!
## Enviando Nossa Transação
Quando terminarmos, devemos recorrer à metodologia ```JQ``` padrão para salvar nossa ```hexstring``` e, em seguida, enviá-la:
```
$ signedtx=$(bitcoin-cli -named signrawtransactionwithkey hexstring=020000000121654fa95d5a268abf96427e3292baed6c9f6d16ed9e80511070f954883864b100000000920047304402201c97b48215f261055e41b765ab025e77a849b349698ed742b305f2c845c69b3f022013a5142ef61db1ff425fbdcdeb3ea370aaff5265eee0956cff9aa97ad9a357e3010047522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352aeffffffff0188130000000000001600142c48d3401f6abed74f52df3f795c644b4398844600000000 prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cVhqpKhx2jgfLUWmyR22JnichoctJCHPtPERm11a2yxnVFKWEKyz"]' | jq -r .hex)
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
99d2b5717fed8875a1ed3b2827dd60ae3089f9caa7c7c23d47635f6f5b397c04
```
## Compreendendo a Importância Desta Metodologia de Assinatura Expandida
Isto deu um belo trabalho e, como logo iremos aprender, existe uma tolice ao utilizar as chaves privadas, o redeem script e com a scriptpubkey pois eles não são realmente necessários para resgatar os endereços de multisg usando versões mais recentes do Bitcoin Core. Então, qual foi o ponto?
Esta metodologia de resgate mostra uma maneira padrão de assinar e reutilizar transações P2SH. Em suma, para resgatar fundos P2SH, uma ```signrawtransactionwithkey``` precisa:
1. Incluir o ```scriptPubKey```, que explica o quebra-cabeça criptográfico P2SH;
2. Incluir o ```redeemScript```, que resolve o quebra-cabeça criptográfico P2SH e apresenta um novo quebra-cabeça;
3. Ser executado em cada máquina que contém as chaves privadas necessárias;
4. Incluir as assinaturas relevantes, que resolvem o quebra-cabeça do redemScript.
Aqui, vimos essa metodologia usada para resgatar os fundos multisig. No futuro, também podemos usá-la para resgatar os fundos que foram trancados com outros scripts P2SH mais complexos, conforme explicado no Capítulo 9.
## Resumo: Gastando uma Transação com Multisig
Acontece que gastar dinheiro enviado para um endereço multisig pode dar um pouco de trabalho. Mas, contanto que tenhamos os endereços originais e nosso redemScript, podemos fazer isso assinando uma transação bruta com cada endereço diferente e fornecendo mais algumas informações ao longo do caminho.
## O Que Vem Depois?
Vamos continuar "Expandindo Transações no Bitcoin com Multisigs" na seção [§6.3: Enviando & Gastando um Multisig Automatizado](06_3_Sending_an_Automated_Multisig.md).

View File

@ -0,0 +1,120 @@
# 6.3: Enviando & Gastando um Multisig Automatizado
A técnica padrão para criar endereços multi-assinatura e gastar os fundos é complexa, mas é um exercício interessante para entender um pouco mais como funcionam e como podemos manipulá-los em um nível relativamente baixo. No entanto, o Bitcoin Core tornou os multisigs mais fáceis de serem manipulados nas novas versões.
> :warning: **AVISO DE VERSÃO:** O comando ```addmultisigaddress``` está disponível no Bitcoin Core v0.10 ou superior.
## Criando um Endereço Multisig em Nossa Carteira
Para tornar os fundos enviados para endereços multisig mais fáceis de serem gastos, só precisamos fazer algumas pré-configurações usando o comando ```addmultisigaddress```. Não é o que gostaríamos de fazer se estivéssemos escrevendo programas de carteiras que utilizam multisig, mas se estivesse apenas tentando receber alguns fundos, isso poderia evitar alguns problemas.
### Coletando as Chaves
Vamos começar criando os endereços P2PKH e recuperando as chaves públicas, como de costume, para cada usuário que fará parte do multisig:
```
machine1$ address3=$(bitcoin-cli getnewaddress)
machine1$ echo $address3
tb1q4ep2vmakpkkj6mflu94x5f94q662m0u5ad0t4w
machine1$ bitcoin-cli -named getaddressinfo address=$address3 | jq -r '. | .pubkey'
0297e681bff16cd4600138449e2527db4b2f83955c691a1b84254ecffddb9bfbfc
machine2$ address4=$(bitcoin-cli getnewaddress)
machine2$ echo $address4
tb1qa9v5h6zkhq8wh0etnv3ae9cdurkh085xufl3de
machine2$ bitcoin-cli -named getaddressinfo address=$address4 | jq -r '. | .pubkey'
02a0d96e16458ff0c90db4826f86408f2cfa0e960514c0db547ff152d3e567738f
```
### Criando o Endereço Multisig em Todos os Lugares
Em seguida, vamos criar o multisig em _cada máquina que contribuiu com assinaturas_ usando um novo comando, ```addmultisigaddress```, ao invés de ```createmultisig```. Este novo comando salva algumas das informações na nossa carteira, tornando muito mais fácil gastar o dinheiro no futuro.
```
machine1$ bitcoin-cli -named addmultisigaddress nrequired=2 keys='''["'$address3'","02a0d96e16458ff0c90db4826f86408f2cfa0e960514c0db547ff152d3e567738f"]'''
{
"address": "tb1q9as46kupwcxancdx82gw65365svlzdwmjal4uxs23t3zz3rgg3wqpqlhex",
"redeemScript": "52210297e681bff16cd4600138449e2527db4b2f83955c691a1b84254ecffddb9bfbfc2102a0d96e16458ff0c90db4826f86408f2cfa0e960514c0db547ff152d3e567738f52ae",
"descriptor": "wsh(multi(2,[d6043800/0'/0'/15']0297e681bff16cd4600138449e2527db4b2f83955c691a1b84254ecffddb9bfbfc,[e9594be8]02a0d96e16458ff0c90db4826f86408f2cfa0e960514c0db547ff152d3e567738f))#wxn4tdju"
}
machine2$ bitcoin-cli -named addmultisigaddress nrequired=2 keys='''["0297e681bff16cd4600138449e2527db4b2f83955c691a1b84254ecffddb9bfbfc","'$address4'"]'''
{
"address": "tb1q9as46kupwcxancdx82gw65365svlzdwmjal4uxs23t3zz3rgg3wqpqlhex",
"redeemScript": "52210297e681bff16cd4600138449e2527db4b2f83955c691a1b84254ecffddb9bfbfc2102a0d96e16458ff0c90db4826f86408f2cfa0e960514c0db547ff152d3e567738f52ae",
"descriptor": "wsh(multi(2,[ae42a66f]0297e681bff16cd4600138449e2527db4b2f83955c691a1b84254ecffddb9bfbfc,[fe6f2292/0'/0'/2']02a0d96e16458ff0c90db4826f86408f2cfa0e960514c0db547ff152d3e567738f))#cc96c5n6"
}
```
Conforme observado na seção anterior, atualmente não importa se usamos endereços ou chaves públicas, então temos mostrado o outro mecanismo aqui, misturando os dois. Iremos obter o mesmo endereço multisig de qualquer maneira. No entanto, _devemos usar a mesma ordem sempre_. Portanto, é melhor que os membros do multisig verifiquem entre si a ordem dos dados para ter certeza de que todos obtiveram o mesmo resultado.
### Atente-se aos Fundos
Depois disso, os membros do multisig ainda precisarão executar o comando ```importaddress``` para observar os fundos recebidos no endereço multisig:
```
machine1$ bitcoin-cli -named importaddress address=2Mzw7WBvh9RAQ4ssKqxyNyP7L9NAojLqSW8 rescan="false"
machine2$ bitcoin-cli -named importaddress address=2Mzw7WBvh9RAQ4ssKqxyNyP7L9NAojLqSW8 rescan="false"
```
## Gastando Novamente com uma Transação Automatizada
Posteriormente, poderemos receber os fundos no endereço multisig normalmente. O uso do ```addmultisigaddress``` é simplesmente uma questão burocrática por parte dos destinatários: um pouco de contabilidade para facilitar a vida deles quando desejarem gastar os saldos.
Mas, isso torna a vida muito mais fácil. Como as informações foram salvas na carteira, os assinantes poderão gastar os fundos enviados para o endereço com várias assinaturas exatamente como qualquer outro endereço, ao invés de assinar sempre em várias máquinas diferentes.
Podemos começar coletando as variáveis, mas não precisamos mais nos preocupar com o ```scriptPubKey``` ou com o ```redeemScript```.
Aqui está uma nova transação enviada para nosso novo endereço multisig:
```
machine1$ utxo_txid=b9f3c4756ef8159d6a66414a4317f865882ee04beb57a0f8349dafcc98f5acbc
machine1$ utxo_vout=0
machine1$ recipient=$(bitcoin-cli getrawchangeaddress)
```
Criamos uma transação bruta:
```
machine1$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.00005}''')
```
E depois, a assinamos:
```
machine1$ bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex
{
"hex": "02000000000101bcacf598ccaf9d34f8a057eb4be02e8865f817434a41666a9d15f86e75c4f3b90000000000ffffffff0188130000000000001600144f93c831ec739166ea425984170f4dc6bac75829040047304402205f84d40ba16ff49e60a7fc9228ef5917473aae1ab667dad01e113ca0fef3008b02201a50da2c65f38798aea94bcbd5bbf065bc1e38de44bacee69d525dcddcc11bba01004752210297e681bff16cd4600138449e2527db4b2f83955c691a1b84254ecffddb9bfbfc2102a0d96e16458ff0c90db4826f86408f2cfa0e960514c0db547ff152d3e567738f52ae00000000",
"complete": false,
"errors": [
{
"txid": "b9f3c4756ef8159d6a66414a4317f865882ee04beb57a0f8349dafcc98f5acbc",
"vout": 0,
"witness": [
"",
"304402205f84d40ba16ff49e60a7fc9228ef5917473aae1ab667dad01e113ca0fef3008b02201a50da2c65f38798aea94bcbd5bbf065bc1e38de44bacee69d525dcddcc11bba01",
"",
"52210297e681bff16cd4600138449e2527db4b2f83955c691a1b84254ecffddb9bfbfc2102a0d96e16458ff0c90db4826f86408f2cfa0e960514c0db547ff152d3e567738f52ae"
],
"scriptSig": "",
"sequence": 4294967295,
"error": "CHECK(MULTI)SIG failing with non-zero signature (possibly need more signatures)"
}
]
}
```
Observe que não precisamos mais dar ajuda extra ao comando ```signrawtransactionwithkey```, porque todas as informações extras já estavam em nossa carteira. Mais importante, não tornamos nossas chaves privadas vulneráveis ao manipulá-las diretamente. Ao invés disso, o processo é _exatamente_ o mesmo que gastar um UTXO normal, exceto que a transação não foi totalmente assinada no final.
### Assinando em Outras Máquinas
A etapa final é exportar o ```hex``` parcialmente assinado para a outra máquina e assinar a transação novamente:
```
machine2$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=02000000014ecda61c45f488e35c613a7c4ae26335a8d7bfd0a942f026d0fb1050e744a67d000000009100473044022025decef887fe2e3eb1c4b3edaa155e5755102d1570716f1467bb0b518b777ddf022017e97f8853af8acab4853ccf502213b7ff4cc3bd9502941369905371545de28d0147522102e7356952f4bb1daf475c04b95a2f7e0d9a12cf5b5c48a25b2303783d91849ba421030186d2b55de166389aefe209f508ce1fbd79966d9ac417adef74b7c1b5e0777652aeffffffff0130e1be07000000001976a9148dfbf103e48df7d1993448aa387dc31a2ebd522d88ac00000000 | jq -r '.hex')
```
Quando todos os assinantes confirmaram a assinatura, estaremos prontos para enviar a transação para a rede:
```
machine2$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
3ce88839ac6165aeadcfb188c490e1b850468eff571b4ca78fac64342751510d
```
Tal como acontece com o atalho discutido na seção [§4.5: Enviando Moedas com Transações Brutas Automatizadas](04_5_Sending_Coins_with_Automated_Raw_Transactions.md), o resultado é muito mais fácil, mas perdemos certo controle no processo.
## Resumo: Enviando & Gastando um Multisig Automatizado
Existe uma maneira mais fácil de gastar fundos enviados para os nossos endereços multisig que simplesmente requerem o uso do comando ```addmultisigaddress``` quando criamos nosso endereço. Ele não demonstra as complexidades do gasto do P2SH e não nos dará um controle abrangente, mas se queremos apenas receber nossas moedas, este pode ser o melhor caminho.
## O Que Vem Depois?
Saiba mais sobre "Expandindo Transações no Bitcoin" no [Capítulo 7: Expandindo Transações no Bitcoin com PSBTs](07_0_Expanding_Bitcoin_Transactions_PSBTs.md).

View File

@ -0,0 +1,24 @@
# Capítulo Sete: Expandindo Transações no Bitcoin com PSBTs
No capítulo anterior, discutimos como usar os multisigs para determinar colaborativamente o consentimento entre várias partes. Essa não é a única forma de colaborar na criação de transações no Bitcoin. Os PSBTs são uma tecnologia muito mais recente que permite que colaboremos em vários estágios, incluindo a criação, financiamento e autenticação de uma transação Bitcoin.
## Objetivos para Esta Seção
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Criar transações com PSBTs;
* Usas ferramentas da linha de comando para completar PSBTs;
* Usar o HWI para interagir com uma hardware wallet.
Os objetivos secundários do capítulo incluem a capacidade de:
* Entender como os PSBTs diferem dos multisig;
* Compreender completamente o fluxo de trabalho com os PSBTs;
* Planejar para todo o poder dos PSBTs;
* Compreender o uso de uma hardware wallet.
## Tabela de Conteúdo
* [Seção Um: Criando uma Transação Parcialmente Assinada no Bitcoin (PSBT)](07_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md)
* [Seção Dois: Usando uma Transação Parcialmente Assinada no Bitcoin (PSBT)](07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md)
* [Seção Três: Integrando com Hardware Wallets](07_3_Integrating_with_Hardware_Wallets.md)

View File

@ -0,0 +1,514 @@
# 7.1: Criando uma Transação Parcialmente Assinada no Bitcoin (PSBT)
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
As Transações Bitcoin Parcialmente Assinadas (Partially Signed Bitcoin Transactions ou mais conhecidas como PSBTs) são a forma mais recente de variar a criação de transações básicas do Bitcoin. Eles fazem isso introduzindo a colaboração em todas as etapas do processo, permitindo que as pessoas (ou sistemas) não apenas autentiquem as transações em conjunto (como nas multisigs), mas também criem, financiem e transmitam facilmente de forma colaborativa.
> :aviso: **AVISO DE VERSÃO:** Esta é uma inovação do Bitcoin Core v 0.17.0. As versões anteriores do Bitcoin Core não funcionarão com o PSBT enquanto estiver em andamento (apesar de conseguir reconhecer a transação final). Algumas atualizações e upgrades para PSBTs continuaram até a versão 0.20.0.
## Entendendo Como PSBTs Funcionam
Os multisigs são ótimos para o caso específico de manter fundos em conjunto e definir regras para quem, entre os signatários conjuntos, poderia autenticar o uso do saldo. Existem muitos casos de uso, como: uma conta conjunta entre cônjuges (uma assinatura 1-de-2); um requisito fiduciário para duplo controle (uma assinatura 2-de-2); e um depósito (uma assinatura 2-de-3).
> :book: ***O que é uma PSBT?*** Como o nome sugere, uma PSBT é uma transação que não foi totalmente assinada. Isso é importante porque, uma vez que uma transação é assinada, seu conteúdo está travado. O [BIP174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki) definiu uma metodologia abstrata para colocar as PSBTs junto que descreve e padroniza funções de criação colaborativa. Um *Criador* propõe uma transação; um ou mais *Atualizadores* a complementam; e um ou mais *Assinantes* a autenticam; antes de um *Finalizador* concluir o processo; e um *Extrator* o transformar em uma transação na rede Bitcoin. Também pode haver um *Combinador* que mescla as PSBTs paralelas de vários usuários.
As PSBTs podem, inicialmente, ter a mesma aparência que os multisigs porque têm um único pedaço de funcionalidade sobreposto: a capacidade de assinar uma transação em conjunto. No entanto, elas foram criadas para um caso de uso totalmente diferente. As PSBTs reconhecem a necessidade de vários programas criarem uma transação em conjunto por vários motivos diferentes e fornecem um formato regularizado para isso. Elas são especialmente úteis para casos de uso envolvendo hardware wallets (veja a seção [§7.3](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/07_3_Integrating_with_Hardware_Wallets.md )), que são protegidas contra acesso total à internet e tendem a ter um histórico mínimo, quando não zero, de transações.
Em geral, as PSBTs fornecem vários elementos funcionais que aprimoram esse caso de uso:
1. Elas fornecem um _padrão_ para criar transações de forma colaborativa, enquanto as metodologias anteriores (incluindo o multisig do capítulo anterior) dependiam de implementação;
2. Elas oferecem suporte a uma _variedade mais ampla de casos de uso_, incluindo financiamento simples em conjunto;
3. Elas suportam _hardware wallets_ e outros casos em que um node pode não ter um histórico completo das transações;
4. Elas opcionalmente permitem a combinação de _transações não serializadas_, não exigindo que um código hexadecimal cada vez maior seja passado de usuário para usuário.
As PSBTs fazem seu trabalho complementando as informações normais da transação com um conjunto de entradas e saídas, cada uma delas definindo tudo o que precisamos saber sobre os UTXOs, de forma que mesmo uma carteira com airgap possa tomar uma decisão informada sobre as assinaturas. Assim, uma entrada lista o saldo de um UTXO e o que precisa ser feito para gastá-lo, enquanto a saída faz o mesmo para os UTXOs que ela está criando.
Esta primeira seção descreverá o processo PSBT padrão com as seguintes funções: Criador, Atualizador, Assinante, Finalizador, Extrator. Faremos isso em uma máquina só, o que irá parecer uma forma complicada de criar uma transação bruta. Mas, tenha fé, há um motivo para isso! Nas seções [§7.2](07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md) e [§7.3](07_3_Integrating_with_Hardware_Wallets.md) vamos ver alguns exemplos reais de como utilizar as PSBTs e vamos transformar este sistema simples em um processo colaborativo compartilhado entre várias máquinas que tem efeitos reais e cria oportunidades reais.
## Criando uma PSBT à Moda Antiga
#### Função na PSBT: Criador
A maneira mais fácil de criar uma PSBT é pegando uma transação existente e usando o comando ```converttopsbt``` para transformá-la em uma PSBT. Certamente, esta não é a _melhor_ maneira, uma vez que requer que façamos uma transação usando um formato (uma transação bruta) e depois convertendo-a para outro (PSBT), mas se tivermos um software antigo que só pode gerar uma transação bruta, pode ser que precisemos utilizá-lo.
Apenas criamos uma transação bruta normalmente:
```
$ utxo_txid_1=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
$ utxo_vout_1=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
$ utxo_txid_2=$(bitcoin-cli listunspent | jq -r '.[1] | .txid')
$ utxo_vout_2=$(bitcoin-cli listunspent | jq -r '.[1] | .vout')
$ echo $utxo_txid_1 $utxo_vout_1 $utxo_txid_2 $utxo_vout_2
c6de60427b28d8ec8102e49771e5d0348fc3ef6a5bf02eb864ec745105a6951b 1 8748eff5f12ca886e3603d9e30227dcb3f0332e0706c4322fec96001f7c7f41c 0
$ recipient=tb1qcaedd724gts3aug73m78c7nfsv9d8zs9q6h2kd
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid_1'", "vout": '$utxo_vout_1' }, { "txid": "'$utxo_txid_2'", "vout": '$utxo_vout_2' } ]''' outputs='''{ "'$recipient'": 0.0000065 }''')
```
Então agora, a convertemos:
```
$ psbt=$(bitcoin-cli -named converttopsbt hexstring=$rawtxhex)
$ echo $psbt
cHNidP8BAHsCAAAAAhuVpgVRdOxkuC7wW2rvw4800OVxl+QCgezYKHtCYN7GAQAAAAD/////HPTH9wFgyf4iQ2xw4DIDP8t9IjCePWDjhqgs8fXvSIcAAAAAAP////8BigIAAAAAAAAWABTHctb5VULhHvEejvx8emmDCtOKBQAAAAAAAAAA
```
É possível notar que a codificação PSBT é muito diferente da transação hexadecimal que estamos acostumados.
Mas, se pudermos, optaremos por criar o PSBT diretamente.
## Criando uma PSBT da Maneira Difícil
#### Função na PSBT: Criador
A primeira metodologia de criação de uma PSBT sem passar por outro formato é usando o comando para PSBT análogo ao ```createrawtransaction```. Usando o ```createpsbt``` teremos o controle máximo a custo do máximo trabalho e da oportunidade máxima de erros.
A CLI deve parecer bastante familiar, a diferença é que agora usamos um novo comando RPC:
```
$ psbt_1=$(bitcoin-cli -named createpsbt inputs='''[ { "txid": "'$utxo_txid_1'", "vout": '$utxo_vout_1' }, { "txid": "'$utxo_txid_2'", "vout": '$utxo_vout_2' } ]''' outputs='''{ "'$recipient'": 0.0000065 }''')
```
A equipe do Bitcoin Core certificou-se de que ```createpsbt``` funcionasse de maneira muito parecida com a```createrawtransaction```, portanto não precisamos aprender uma nova sintaxe diferente.
Podemos verificar se a nova PSBT é a mesma criada pelo ```converttopsbt```:
```
$ echo $psbt_1
cHNidP8BAHsCAAAAAhuVpgVRdOxkuC7wW2rvw4800OVxl+QCgezYKHtCYN7GAQAAAAD/////HPTH9wFgyf4iQ2xw4DIDP8t9IjCePWDjhqgs8fXvSIcAAAAAAP////8BigIAAAAAAAAWABTHctb5VULhHvEejvx8emmDCtOKBQAAAAAAAAAA
$ if [ "$psbt" == "$psbt_1" ]; then echo "PSBTs are equal"; else echo "PSBTs are not equal"; fi
PSBTs are equal
```
## Examinando uma PSBT
#### Função na PSBT: Qualquer Uma
Então, como a nossa PSBT realmente se parece? Podemos ver isso com o comando ```decodepsbt```:
```
$ bitcoin-cli -named decodepsbt psbt=$psbt
{
"tx": {
"txid": "ea73a631b456d2b041ed73bf5767946408c6ff067716929a68ecda2e3e4de6d3",
"hash": "ea73a631b456d2b041ed73bf5767946408c6ff067716929a68ecda2e3e4de6d3",
"version": 2,
"size": 123,
"vsize": 123,
"weight": 492,
"locktime": 0,
"vin": [
{
"txid": "c6de60427b28d8ec8102e49771e5d0348fc3ef6a5bf02eb864ec745105a6951b",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
},
{
"txid": "8748eff5f12ca886e3603d9e30227dcb3f0332e0706c4322fec96001f7c7f41c",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00000650,
"n": 0,
"scriptPubKey": {
"asm": "0 c772d6f95542e11ef11e8efc7c7a69830ad38a05",
"hex": "0014c772d6f95542e11ef11e8efc7c7a69830ad38a05",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1qcaedd724gts3aug73m78c7nfsv9d8zs9q6h2kd"
]
}
}
]
},
"unknown": {
},
"inputs": [
{
},
{
}
],
"outputs": [
{
}
]
}
```
É importante notar que, embora tenhamos definido os fundamentos da transação: os ```vins``` de onde o dinheiro está vindo e os ```vouts``` para onde está indo, ainda não definimos os ```inputs``` e os ```outputs``` que são o coração da PSBT e que são necessários para os usuários offline avaliá-las. Isso já é esperado: o papel do Criador conforme definido no [BIP174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki) é delinear a transação, enquanto o papel do Atualizador é começar a preencher os dados específicos da PSBT. (Outros comandos combinam as funções de Criador e Atualizador, mas o ```createpsbt``` não, porque não tem acesso à nossa carteira).
Também podemos usar o comando ```analyzepsbt``` para verificar nosso estado atual:
```
standup@btctest20:~$ bitcoin-cli -named analyzepsbt psbt=$psbt
{
"inputs": [
{
"has_utxo": false,
"is_final": false,
"next": "updater"
},
{
"has_utxo": false,
"is_final": false,
"next": "updater"
}
],
"next": "updater"
}
```
Da mesma forma, o comando ```analysepsbt``` nos mostra uma PSBT que precisa ser trabalhada. Damos uma olhada em cada um dos dois `inputs` (correspondendo aos dois ```vins```), e nenhum deles possui as informações de que precisamos.
## Finalizando uma PSBT
#### Funções na PSBT: Atualizador, Assinante e Finalizador
Existe o comando ```utxoupdatepsbt``` que pode ser usado para atualizar UTXOs, importando as informações do descritor manualmente, mas não queremos usá-lo a menos que tenhamos um caso de uso em que não tenhamos todas as informações nas carteiras de todos que irão assinar a PSBT.
> :information_source: **NOTA:** Se escolhermos Atualizar a PSBT com o ```utxoupdatepsbt```, ainda precisaremos usar o ```walletprocesspsbt``` para assiná-lo: é o único comando que a função Assinante possui em PSBTs que está disponível no `bitcoin-cli`.
Ao invés disso, devemos usar o ```walletprocesspsbt```, que irá atualizar, assinar e finalizar:
```
$ bitcoin-cli walletprocesspsbt $psbt
{
"psbt": "cHNidP8BAHsCAAAAAhuVpgVRdOxkuC7wW2rvw4800OVxl+QCgezYKHtCYN7GAQAAAAD/////HPTH9wFgyf4iQ2xw4DIDP8t9IjCePWDjhqgs8fXvSIcAAAAAAP////8BigIAAAAAAAAWABTHctb5VULhHvEejvx8emmDCtOKBQAAAAAAAQEfAQAAAAAAAAAWABRsRdOvqHYghsS9dtinGsfJduGRlgEIawJHMEQCIAqJbxz6dBzNpfaDu4XZXb+DbDkM3UWnhezh9UdmeVghAiBRxMlW2o0wEtphtUZRWIiJOaGtXfsQbB4lovkvE4eRIgEhArrDpkX9egpTfGJ6039faVBYxY0ZzrADPpE/Gpl14A3uAAEBH0gDAAAAAAAAFgAU1ZEJG4B0ojde2ZhanEsY7+z9QWUBCGsCRzBEAiB+sNNCO4xiFQ+DoHVrqqk9yM0V4H9ZSyExx1PW7RbjsgIgUeWkQ3L7aAv1xIe7h+8PZb8ECsXg1UzbtPW8wd2qx0UBIQKIO7VGPjfVUlLYs9XCFBsAezfIp9tiEfdclVrMXqMl6wAA",
"complete": true
}
```
Obviamente, precisaremos salvar as informações da ```psbt``` usando```JQ```:
```
$ psbt_f=$(bitcoin-cli walletprocesspsbt $psbt | jq -r '.psbt')
```
Podemos ver que os `inputs` foram preenchidos:
```
$ bitcoin-cli decodepsbt $psbt_f
{
"tx": {
"txid": "ea73a631b456d2b041ed73bf5767946408c6ff067716929a68ecda2e3e4de6d3",
"hash": "ea73a631b456d2b041ed73bf5767946408c6ff067716929a68ecda2e3e4de6d3",
"version": 2,
"size": 123,
"vsize": 123,
"weight": 492,
"locktime": 0,
"vin": [
{
"txid": "c6de60427b28d8ec8102e49771e5d0348fc3ef6a5bf02eb864ec745105a6951b",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
},
{
"txid": "8748eff5f12ca886e3603d9e30227dcb3f0332e0706c4322fec96001f7c7f41c",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00000650,
"n": 0,
"scriptPubKey": {
"asm": "0 c772d6f95542e11ef11e8efc7c7a69830ad38a05",
"hex": "0014c772d6f95542e11ef11e8efc7c7a69830ad38a05",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1qcaedd724gts3aug73m78c7nfsv9d8zs9q6h2kd"
]
}
}
]
},
"unknown": {
},
"inputs": [
{
"witness_utxo": {
"amount": 0.00000001,
"scriptPubKey": {
"asm": "0 6c45d3afa8762086c4bd76d8a71ac7c976e19196",
"hex": "00146c45d3afa8762086c4bd76d8a71ac7c976e19196",
"type": "witness_v0_keyhash",
"address": "tb1qd3za8tagwcsgd39awmv2wxk8e9mwryvktqmkkg"
}
},
"final_scriptwitness": [
"304402200a896f1cfa741ccda5f683bb85d95dbf836c390cdd45a785ece1f54766795821022051c4c956da8d3012da61b5465158888939a1ad5dfb106c1e25a2f92f1387912201",
"02bac3a645fd7a0a537c627ad37f5f695058c58d19ceb0033e913f1a9975e00dee"
]
},
{
"witness_utxo": {
"amount": 0.00000840,
"scriptPubKey": {
"asm": "0 d591091b8074a2375ed9985a9c4b18efecfd4165",
"hex": "0014d591091b8074a2375ed9985a9c4b18efecfd4165",
"type": "witness_v0_keyhash",
"address": "tb1q6kgsjxuqwj3rwhkenpdfcjccalk06st9z0k0kh"
}
},
"final_scriptwitness": [
"304402207eb0d3423b8c62150f83a0756baaa93dc8cd15e07f594b2131c753d6ed16e3b2022051e5a44372fb680bf5c487bb87ef0f65bf040ac5e0d54cdbb4f5bcc1ddaac74501",
"02883bb5463e37d55252d8b3d5c2141b007b37c8a7db6211f75c955acc5ea325eb"
]
}
],
"outputs": [
{
}
],
"fee": 0.00000191
}
```
Ou para ser mais preciso: (1) a PSBT foi atualizada com as informações de ```witness_utxo```; (2) a PSBT foi assinada; e (3) a PSBT foi finalizada.
## Criando uma PSBT da Maneira Fácil
#### Função na PSBT: Criador e Atualizador
Se esperamos que haja um comando equivalente ao ```fundrawtransaction```, ficaremos satisfeitos em saber que existe: ele é o ```walletcreatefundedpsbt```. Podemos usá-lo da mesma forma que ```createpsbt```:
```
$ bitcoin-cli -named walletcreatefundedpsbt inputs='''[ { "txid": "'$utxo_txid_1'", "vout": '$utxo_vout_1' }, { "txid": "'$utxo_txid_2'", "vout": '$utxo_vout_2' } ]''' outputs='''{ "'$recipient'": 0.0000065 }'''
{
"psbt": "cHNidP8BAOwCAAAABBuVpgVRdOxkuC7wW2rvw4800OVxl+QCgezYKHtCYN7GAQAAAAD/////HPTH9wFgyf4iQ2xw4DIDP8t9IjCePWDjhqgs8fXvSIcAAAAAAP/////uFwerANKjyVK6WaR7gzlX+lOf+ORsfjP5LYCSNIbhaAAAAAAA/v///4XjOeey0NyGpJYpszNWF8AFNiuFaWsjkOrk35Jp+9kKAAAAAAD+////AtYjEAAAAAAAFgAUMPsier2ey1eH48oGqrbbYGzNHgKKAgAAAAAAABYAFMdy1vlVQuEe8R6O/Hx6aYMK04oFAAAAAAABAR8BAAAAAAAAABYAFGxF06+odiCGxL122Kcax8l24ZGWIgYCusOmRf16ClN8YnrTf19pUFjFjRnOsAM+kT8amXXgDe4Q1gQ4AAAAAIABAACADgAAgAABAR9IAwAAAAAAABYAFNWRCRuAdKI3XtmYWpxLGO/s/UFlIgYCiDu1Rj431VJS2LPVwhQbAHs3yKfbYhH3XJVazF6jJesQ1gQ4AAAAAIABAACADAAAgAABAIwCAAAAAdVmsvkSBmfeHqNAe/wDCQ5lEp9F/587ftzCD1UL60nMAQAAABcWABRzFxRJfFPl8FJ6SxjAJzy3mCAMXf7///8CQEIPAAAAAAAZdqkUf0NzebzGbEB0XtwYkeprODDhl12IrMEwLQAAAAAAF6kU/d+kMX6XijmD+jWdUrLZlJUnH2iHPhQbACIGA+/e40wACf0XXzsgteWlUX/V0WdG8uY1tEYXra/q68OIENYEOAAAAACAAAAAgBIAAIAAAQEfE4YBAAAAAAAWABTVkQkbgHSiN17ZmFqcSxjv7P1BZSIGAog7tUY+N9VSUtiz1cIUGwB7N8in22IR91yVWsxeoyXrENYEOAAAAACAAQAAgAwAAIAAIgICKMavAB+71Adqsbf+XtC1g/OlmLEuTp3U0axyeu/LAI0Q1gQ4AAAAAIABAACAGgAAgAAA",
"fee": 0.00042300,
"changepos": 0
}
```
No entanto, a grande vantagem é que podemos usá-lo para se autofinanciar, deixando de fora os ```inputs```, assim como o ```fundrawtransaction```.
```
$ psbt_new=$(bitcoin-cli -named walletcreatefundedpsbt inputs='''[]''' outputs='''{ "'$recipient'": 0.0000065 }''' | jq -r '.psbt')
$ bitcoin-cli decodepsbt $psbt_new
{
"tx": {
"txid": "9f2c6205ac797c1020f7f261e3ab71cd0699ff4b1a8934f68b273c71547e235f",
"hash": "9f2c6205ac797c1020f7f261e3ab71cd0699ff4b1a8934f68b273c71547e235f",
"version": 2,
"size": 154,
"vsize": 154,
"weight": 616,
"locktime": 0,
"vin": [
{
"txid": "8748eff5f12ca886e3603d9e30227dcb3f0332e0706c4322fec96001f7c7f41c",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967294
},
{
"txid": "68e1863492802df9337e6ce4f89f53fa5739837ba459ba52c9a3d200ab0717ee",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.00971390,
"n": 0,
"scriptPubKey": {
"asm": "0 09a74ef0bae4d68b0b2ec9a7c4557a2b5c85bd8b",
"hex": "001409a74ef0bae4d68b0b2ec9a7c4557a2b5c85bd8b",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1qpxn5au96untgkzewexnug4t69dwgt0vtfahcv6"
]
}
},
{
"value": 0.00000650,
"n": 1,
"scriptPubKey": {
"asm": "0 c772d6f95542e11ef11e8efc7c7a69830ad38a05",
"hex": "0014c772d6f95542e11ef11e8efc7c7a69830ad38a05",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1qcaedd724gts3aug73m78c7nfsv9d8zs9q6h2kd"
]
}
}
]
},
"unknown": {
},
"inputs": [
{
"witness_utxo": {
"amount": 0.00000840,
"scriptPubKey": {
"asm": "0 d591091b8074a2375ed9985a9c4b18efecfd4165",
"hex": "0014d591091b8074a2375ed9985a9c4b18efecfd4165",
"type": "witness_v0_keyhash",
"address": "tb1q6kgsjxuqwj3rwhkenpdfcjccalk06st9z0k0kh"
}
},
"bip32_derivs": [
{
"pubkey": "02883bb5463e37d55252d8b3d5c2141b007b37c8a7db6211f75c955acc5ea325eb",
"master_fingerprint": "d6043800",
"path": "m/0'/1'/12'"
}
]
},
{
"non_witness_utxo": {
"txid": "68e1863492802df9337e6ce4f89f53fa5739837ba459ba52c9a3d200ab0717ee",
"hash": "68e1863492802df9337e6ce4f89f53fa5739837ba459ba52c9a3d200ab0717ee",
"version": 2,
"size": 140,
"vsize": 140,
"weight": 560,
"locktime": 1774654,
"vin": [
{
"txid": "cc49eb0b550fc2dc7e3b9fff459f12650e0903fc7b40a31ede670612f9b266d5",
"vout": 1,
"scriptSig": {
"asm": "0014731714497c53e5f0527a4b18c0273cb798200c5d",
"hex": "160014731714497c53e5f0527a4b18c0273cb798200c5d"
},
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.01000000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 7f437379bcc66c40745edc1891ea6b3830e1975d OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9147f437379bcc66c40745edc1891ea6b3830e1975d88ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"ms7ruzvL4atCu77n47dStMb3of6iScS8kZ"
]
}
},
{
"value": 0.02961601,
"n": 1,
"scriptPubKey": {
"asm": "OP_HASH160 fddfa4317e978a3983fa359d52b2d99495271f68 OP_EQUAL",
"hex": "a914fddfa4317e978a3983fa359d52b2d99495271f6887",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"2NGParh82hE2Zif5PVK3AfLpYhfwF5FyRGr"
]
}
}
]
},
"bip32_derivs": [
{
"pubkey": "03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388",
"master_fingerprint": "d6043800",
"path": "m/0'/0'/18'"
}
]
}
],
"outputs": [
{
"bip32_derivs": [
{
"pubkey": "029bb586a52657dd98852cecef78552a4e21d081a7a30e4008ce9b419840d4deac",
"master_fingerprint": "d6043800",
"path": "m/0'/1'/27'"
}
]
},
{
}
],
"fee": 0.00028800
}
```
Como podemos ver, criamos a PSBT e depois a atualizamos com todas as informações que encontramos localmente.
A partir daí, precisamos usar o ```walletprocesspsbt``` para finalizar, como de costume:
```
$ psbt_new_f=$(bitcoin-cli walletprocesspsbt $psbt_new | jq -r '.psbt')
```
Posteriormente, uma análise mostrará que também está pronto:
```
$ bitcoin-cli analyzepsbt $psbt_new_f
{
"inputs": [
{
"has_utxo": true,
"is_final": true,
"next": "extractor"
},
{
"has_utxo": true,
"is_final": true,
"next": "extractor"
}
],
"estimated_vsize": 288,
"estimated_feerate": 0.00100000,
"fee": 0.00028800,
"next": "extractor"
}
```
Agora, realmente gostaríamos de usar o ```walletcreatefundedpsbt``` se estivermos criando um programa com o ```bitcoin-cli```? Provavelmente não. Mas é a mesma análise que fazemos com o ```fundrawtransaction```. Deixamos o Bitcoin Core fazer a análise, o cálculo e as decisões, ou nós mesmos fazemos?
## Enviando uma PSBT
#### Função na PSBT: Extrator
Para finalizar a PSBT, usamos o ```finalizepsbt```, que irá transformar a PSBT novamente em hexadecimal. (Também assumirá a função de Finalizador, caso ainda não tenha acontecido).
```
$ bitcoin-cli finalizepsbt $psbt_f
{
"hex": "020000000001021b95a6055174ec64b82ef05b6aefc38f34d0e57197e40281ecd8287b4260dec60100000000ffffffff1cf4c7f70160c9fe22436c70e032033fcb7d22309e3d60e386a82cf1f5ef48870000000000ffffffff018a02000000000000160014c772d6f95542e11ef11e8efc7c7a69830ad38a050247304402200a896f1cfa741ccda5f683bb85d95dbf836c390cdd45a785ece1f54766795821022051c4c956da8d3012da61b5465158888939a1ad5dfb106c1e25a2f92f13879122012102bac3a645fd7a0a537c627ad37f5f695058c58d19ceb0033e913f1a9975e00dee0247304402207eb0d3423b8c62150f83a0756baaa93dc8cd15e07f594b2131c753d6ed16e3b2022051e5a44372fb680bf5c487bb87ef0f65bf040ac5e0d54cdbb4f5bcc1ddaac745012102883bb5463e37d55252d8b3d5c2141b007b37c8a7db6211f75c955acc5ea325eb00000000",
"complete": true
}
```
Como de costume, vamos querer salvar e depois enviar.
```
$ psbt_hex=$(bitcoin-cli finalizepsbt $psbt_f | jq -r '.hex')
$ bitcoin-cli -named sendrawtransaction hexstring=$psbt_hex
ea73a631b456d2b041ed73bf5767946408c6ff067716929a68ecda2e3e4de6d3
```
## Revisando o Fluxo de Trabalho
Ao criar software ```bitcoin-cli```, é mais provável que iremos cumprir as cinco funções principais dos PSBTs usando os comandos ```createpsbt```, ```walletprocesspsbt``` e ```finalizepsbt```. Esta é a aparência desse fluxo:
![](images/psbt-roles-for-cli-1.png)
Se escolhermos usar o atalho de ```walletcreatefundedpsbt```, teremos um fluxo mais ou menos assim:
![](images/psbt-roles-for-cli-2.png)
Finalmente, se precisarmos de mais controle e optarmos por usar o comando ```utxoupdatepsbt``` (que não está documentado aqui), teremos um fluxo de trabalho assim:
![](images/psbt-roles-for-cli-3.png)
## Resumo: Criando uma Transação Parcialmente Assinada no Bitcoin (PSBT)
A criação de uma PSBT envolve um fluxo de trabalho um tanto complexo de criação, atualização, assinatura, finalização e extração da PSBT, após o qual ela se converte novamente em uma transação bruta. Por que teríamos tanto trabalho? Porque desejamos colaborar entre vários usuários ou vários programas. Agora que entendemos esse fluxo de trabalho, a próxima seção irá apresentar alguns exemplos reais de como fazer isso.
## O Que Vem Depois?
Vamos continuar "Expandindo Transações no Bitcoin com PSBTs" na seção [§7.2: Usando uma Transação Parcialmente Assinada no Bitcoin (PSBT)](07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md).

View File

@ -0,0 +1,601 @@
# 7.2: Usando uma Transação Parcialmente Assinada no Bitcoin (PSBT)
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Agora que aprendemos o fluxo de trabalho básico para gerar uma PSBT, provavelmente desejamos fazer algo com ela. O que as PSBTs podem fazer que os multisigs (e as transações brutas normais) não podem? Para começar, temos a facilidade de usar um formato padronizado, o que significa que podemos usar nossas transações do ```bitcoin-cli``` e combiná-las com transações geradas por pessoas (ou programas) em outras plataformas. Além disso, podemos fazer algumas coisas que simplesmente não eram fáceis usando outros mecanismos.
A seguir estão três exemplos do uso das PSBTs para: multisigs, financiamentos e CoinJoins.
> :aviso: **AVISO DE VERSÃO:** Esta é uma inovação do Bitcoin Core v0.17.0. As versões anteriores do Bitcoin Core não funcionarão com a PSBT enquanto estiver em andamento (embora ainda consigam reconhecer a transação final).
## Usando uma PSBT para Gastar Fundos MultiSig
Suponha que tenhamos criado um endereço multisig, assim como fizemos na seção [§6.3](06_3_Sending_an_Automated_Multisig.md).
```
machine1$ bitcoin-cli -named addmultisigaddress nrequired=2 keys='''["'$pubkey1'","'$pubkey2'"]'''
{
"address": "tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0",
"redeemScript": "5221038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e2103789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd063652ae",
"descriptor": "wsh(multi(2,[d6043800/0'/0'/26']038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e,[be686772]03789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd0636))#07zyayfk"
}
machine1$ bitcoin-cli -named importaddress address="tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0" rescan=false
machine2$ bitcoin-cli -named addmultisigaddress nrequired=2 keys='''["'$pubkey1'","'$pubkey2'"]'''
{
"address": "tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0",
"redeemScript": "5221038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e2103789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd063652ae",
"descriptor": "wsh(multi(2,[d6043800/0'/0'/26']038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e,[be686772]03789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd0636))#07zyayfk"
}
machine2$ bitcoin-cli -named importaddress address="tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0" rescan=false
```
E que tenhamos algumas moedas:
```
$ bitcoin-cli listunspent
[
{
"txid": "53ec62c5c2fe8b16ee2164e9699d16c7b8ac30ec53a696e55f09b79704b539b5",
"vout": 0,
"address": "tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0",
"label": "",
"witnessScript": "5221038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e2103789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd063652ae",
"scriptPubKey": "0020224cb503a7f7835799b9c22ee0c3c7d93d090356e30e70015c3ebbfa515a3074",
"amount": 0.01999800,
"confirmations": 2,
"spendable": false,
"solvable": true,
"desc": "wsh(multi(2,[d6043800/0'/0'/26']038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e,[be686772]03789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd0636))#07zyayfk",
"safe": true
}
]
```
Nós _poderíamos_ gastá-las usando os mecanismos do [Capítulo 6](06_0_Expanding_Bitcoin_Transactions_Multisigs.md), onde assinamos serialmente uma transação, mas ao invés disso, vamos mostrar a vantagem das PSBTs para o uso dos multisigs. Podemos gerar uma única PSBT, permitir que todos a assinem em paralelo e depois podemos combinar todos resultados! Não há mais a necessidade de passar o arquivo hexadecimal em constante expansão de pessoa para pessoa, o que acelera as coisas e reduz as chances de erros.
Para demonstrar essa metodologia, vamos extrair aquele 0,02 BTC do multisig e dividi-lo entre os dois assinantes, cada um deles gerando um novo endereço com esse propósito:
```
machine1$ bitcoin-cli getnewaddress
tb1qem5l3q5g5h6fsqv352xh4cy07kzq2rd8gphqma
machine2$ bitcoin-cli getnewaddress
tb1q3krplahg4ncu523m8h2eephjazs2hf6ur8r6zp
```
A primeira coisa que fazemos é criar uma PSBT em uma máquina. (Não importa qual). Precisamos usar o ```createpsbt``` da seção [§7.1](07_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md) para isso, e não o comando mais simples ```walletcreatefundedpsbt```, porque precisamos do controle extra de selecionar o dinheiro protegido pelo multisig. (Este será o caso para todos os três exemplos nesta seção, o que demonstra por quê geralmente precisamos usar o ```createpsbt``` para coisas mais complexas.
```
machine1$ utxo_txid=53ec62c5c2fe8b16ee2164e9699d16c7b8ac30ec53a696e55f09b79704b539b5
machine1$ utxo_vout=0
machine1$ split1=tb1qem5l3q5g5h6fsqv352xh4cy07kzq2rd8gphqma
machine1$ split2=tb1q3krplahg4ncu523m8h2eephjazs2hf6ur8r6zp
machine1$ psbt=$(bitcoin-cli -named createpsbt inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$split1'": 0.009998,"'$split2'": 0.009998 }''')
```
Em seguida, precisamos enviar essa $psbt a todo mundo para que assinem:
```
machine1$ echo $psbt
cHNidP8BAHECAAAAAbU5tQSXtwlf5ZamU+wwrLjHFp1p6WQh7haL/sLFYuxTAAAAAAD/////AnhBDwAAAAAAFgAUzun4goil9JgBkaKNeuCP9YQFDad4QQ8AAAAAABYAFI2GH/borPHKKjs91ZyG8uigq6dcAAAAAAAAAAA=
```
Mas você só precisa enviar uma vez! E você faz isso simultaneamente.
Aqui está o resultado da primeira máquina, onde geramos a PSBT:
```
machine1$ psbt_p1=$(bitcoin-cli walletprocesspsbt $psbt | jq -r '.psbt')
machine1$ bitcoin-cli decodepsbt $psbt_p1
{
"tx": {
"txid": "1687e89fcb9dd3067f75495b4884dc1d4d1cf05a6c272b783cfe29eb5d22e985",
"hash": "1687e89fcb9dd3067f75495b4884dc1d4d1cf05a6c272b783cfe29eb5d22e985",
"version": 2,
"size": 113,
"vsize": 113,
"weight": 452,
"locktime": 0,
"vin": [
{
"txid": "25e8a26f60cf485768a1e6953b983675c867b7ab126b02e753c47b7db0c4be5e",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00499900,
"n": 0,
"scriptPubKey": {
"asm": "0 cee9f88288a5f4980191a28d7ae08ff584050da7",
"hex": "0014cee9f88288a5f4980191a28d7ae08ff584050da7",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1qem5l3q5g5h6fsqv352xh4cy07kzq2rd8gphqma"
]
}
},
{
"value": 0.00049990,
"n": 1,
"scriptPubKey": {
"asm": "0 8d861ff6e8acf1ca2a3b3dd59c86f2e8a0aba75c",
"hex": "00148d861ff6e8acf1ca2a3b3dd59c86f2e8a0aba75c",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1q3krplahg4ncu523m8h2eephjazs2hf6ur8r6zp"
]
}
}
]
},
"unknown": {
},
"inputs": [
{
"witness_utxo": {
"amount": 0.01000000,
"scriptPubKey": {
"asm": "0 2abb5d49ce7e753cbf5a9ffa8cdaf815bf1074f5c0bf495a93df8eb5112f65aa",
"hex": "00202abb5d49ce7e753cbf5a9ffa8cdaf815bf1074f5c0bf495a93df8eb5112f65aa",
"type": "witness_v0_scripthash",
"address": "tb1q92a46jww0e6ne066nlagekhczkl3qa84czl5jk5nm78t2yf0vk4qte328m"
}
},
"partial_signatures": {
"03f52980d322acaf084bcef3216f3d84bfb672d1db26ce2861de3ec047bede140d": "304402203abb95d1965e4cea630a8b4890456d56698ff2dd5544cb79303cc28cb011cbb40220701faa927f8a19ca79b09d35c78d8d0a2187872117d9308805f7a896b07733f901"
},
"witness_script": {
"asm": "2 033055ec2da9bbb34c2acb343692bfbecdef8fab8d114f0036eba01baec3888aa0 03f52980d322acaf084bcef3216f3d84bfb672d1db26ce2861de3ec047bede140d 2 OP_CHECKMULTISIG",
"hex": "5221033055ec2da9bbb34c2acb343692bfbecdef8fab8d114f0036eba01baec3888aa02103f52980d322acaf084bcef3216f3d84bfb672d1db26ce2861de3ec047bede140d52ae",
"type": "multisig"
},
"bip32_derivs": [
{
"pubkey": "033055ec2da9bbb34c2acb343692bfbecdef8fab8d114f0036eba01baec3888aa0",
"master_fingerprint": "c1fdfe64",
"path": "m"
{
"tx": {
"txid": "ee82d3e0d225e0fb919130d68c5052b6e3c362c866acc54d89af975330bb4d16",
"hash": "ee82d3e0d225e0fb919130d68c5052b6e3c362c866acc54d89af975330bb4d16",
"version": 2,
"size": 113,
"vsize": 113,
"weight": 452,
"locktime": 0,
"vin": [
{
"txid": "53ec62c5c2fe8b16ee2164e9699d16c7b8ac30ec53a696e55f09b79704b539b5",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00999800,
"n": 0,
"scriptPubKey": {
"asm": "0 cee9f88288a5f4980191a28d7ae08ff584050da7",
"hex": "0014cee9f88288a5f4980191a28d7ae08ff584050da7",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1qem5l3q5g5h6fsqv352xh4cy07kzq2rd8gphqma"
]
}
},
{
"value": 0.00999800,
"n": 1,
"scriptPubKey": {
"asm": "0 8d861ff6e8acf1ca2a3b3dd59c86f2e8a0aba75c",
"hex": "00148d861ff6e8acf1ca2a3b3dd59c86f2e8a0aba75c",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1q3krplahg4ncu523m8h2eephjazs2hf6ur8r6zp"
]
}
}
]
},
"unknown": {
},
"inputs": [
{
"witness_utxo": {
"amount": 0.01999800,
"scriptPubKey": {
"asm": "0 224cb503a7f7835799b9c22ee0c3c7d93d090356e30e70015c3ebbfa515a3074",
"hex": "0020224cb503a7f7835799b9c22ee0c3c7d93d090356e30e70015c3ebbfa515a3074",
"type": "witness_v0_scripthash",
"address": "tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0"
}
},
"partial_signatures": {
"038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e": "3044022040aae4f2ba37b1526524195f4a325d97d1317227b3c82aea55c5abd66810a7ec0220416e7c03e70a31232044addba454d6b37b6ace39ab163315d3293e343ae9513301"
},
"witness_script": {
"asm": "2 038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e 03789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd0636 2 OP_CHECKMULTISIG",
"hex": "5221038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e2103789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd063652ae",
"type": "multisig"
},
"bip32_derivs": [
{
"pubkey": "03789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd0636",
"master_fingerprint": "be686772",
"path": "m"
},
{
"pubkey": "038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e",
"master_fingerprint": "d6043800",
"path": "m/0'/0'/26'"
}
]
}
],
"outputs": [
{
"bip32_derivs": [
{
"pubkey": "02fce26085452d07abc63bd389cb7dba9871e79bbecd08039291226be8232a9000",
"master_fingerprint": "d6043800",
"path": "m/0'/0'/24'"
}
]
},
{
}
],
"fee": 0.00000200
}
machine1$ bitcoin-cli analyzepsbt $psbt_p1
{
"inputs": [
{
"has_utxo": true,
"is_final": false,
"next": "signer",
"missing": {
"signatures": [
"be6867729bcc35ed065bb4c937557d371218a8e2"
]
}
}
],
"estimated_vsize": 168,
"estimated_feerate": 0.00001190,
"fee": 0.00000200,
"next": "signer"
}
```
Isso demonstra que as informações do UTXO foram importadas e que há uma _assinatura parcial_, mas que uma assinatura ainda não a deixa completa.
Aqui temos o mesmo resultado na outra máquina:
```
machine2$ psbt=cHNidP8BAHECAAAAAbU5tQSXtwlf5ZamU+wwrLjHFp1p6WQh7haL/sLFYuxTAAAAAAD/////AnhBDwAAAAAAFgAUzun4goil9JgBkaKNeuCP9YQFDad4QQ8AAAAAABYAFI2GH/borPHKKjs91ZyG8uigq6dcAAAAAAAAAAA=
machine2$ psbt_p2=$(bitcoin-cli walletprocesspsbt $psbt | jq -r '.psbt')
machine3$ echo $psbt_p2
cHNidP8BAHECAAAAAbU5tQSXtwlf5ZamU+wwrLjHFp1p6WQh7haL/sLFYuxTAAAAAAD/////AnhBDwAAAAAAFgAUzun4goil9JgBkaKNeuCP9YQFDad4QQ8AAAAAABYAFI2GH/borPHKKjs91ZyG8uigq6dcAAAAAAABASu4gx4AAAAAACIAICJMtQOn94NXmbnCLuDDx9k9CQNW4w5wAVw+u/pRWjB0IgIDeJ9UNCNnDhaWZ/9+Hy2iqX3xsJEicuFC1YJFGs69BjZHMEQCIDJ71isvR2We6ym1QByLV5SQ+XEJD0SAP76fe1JU5PZ/AiB3V7ejl2H+9LLS6ubqYr/bSKfRfEqrp2FCMISjrWGZ6QEBBUdSIQONc63yx+oz+dw0t3titZr0M8HenHYzMtp56D4VX5YDDiEDeJ9UNCNnDhaWZ/9+Hy2iqX3xsJEicuFC1YJFGs69BjZSriIGA3ifVDQjZw4Wlmf/fh8toql98bCRInLhQtWCRRrOvQY2ENPtiCUAAACAAAAAgAYAAIAiBgONc63yx+oz+dw0t3titZr0M8HenHYzMtp56D4VX5YDDgRZu4lPAAAiAgNJzEMyT3rZS7QHqb8SvFCv2ee0MKRyVy8bY8tVUDT1KhDT7YglAAAAgAAAAIADAACAAA==
```
Observe novamente que gerenciamos a assinatura deste multisig gerando uma PSBT totalmente sem assinatura com o UTXO correto, permitindo que cada um dos usuários processe essa PSBT por conta própria, adicionando entradas e assinaturas. Como resultado, temos duas PSBTs, cada uma contendo apenas uma assinatura. Isso não funcionaria no cenário multisig clássico, porque todas as assinaturas devem ser serializadas. Porém, podemos assinar em paralelo neste momento, e em seguida, usar a função Combinador para juntá-las.
Vamos novamente a qualquer uma das máquinas e vamos nos certificar de que temos as duas PSBTs nas variáveis e, em seguida, vamos combiná-las:
```
machine1$ psbt_p2="cHNidP8BAHECAAAAAbU5tQSXtwlf5ZamU+wwrLjHFp1p6WQh7haL/sLFYuxTAAAAAAD/////AnhBDwAAAAAAFgAUzun4goil9JgBkaKNeuCP9YQFDad4QQ8AAAAAABYAFI2GH/borPHKKjs91ZyG8uigq6dcAAAAAAABAIcCAAAAAtu5pTheUzdsTaMCEPj3XKboMAyYzABmIIeOWMhbhTYlAAAAAAD//////uSTLbibcqSd/Z9ieSBWJ2psv+9qvoGrzWEa60rCx9cAAAAAAP////8BuIMeAAAAAAAiACAiTLUDp/eDV5m5wi7gw8fZPQkDVuMOcAFcPrv6UVowdAAAAAAAACICA0nMQzJPetlLtAepvxK8UK/Z57QwpHJXLxtjy1VQNPUqENPtiCUAAACAAAAAgAMAAIAA"
machine2$ psbt_c=$(bitcoin-cli combinepsbt '''["'$psbt_p1'", "'$psbt_p2'"]''')
$ bitcoin-cli decodepsbt $psbt_c
{
"tx": {
"txid": "ee82d3e0d225e0fb919130d68c5052b6e3c362c866acc54d89af975330bb4d16",
"hash": "ee82d3e0d225e0fb919130d68c5052b6e3c362c866acc54d89af975330bb4d16",
"version": 2,
"size": 113,
"vsize": 113,
"weight": 452,
"locktime": 0,
"vin": [
{
"txid": "53ec62c5c2fe8b16ee2164e9699d16c7b8ac30ec53a696e55f09b79704b539b5",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00999800,
"n": 0,
"scriptPubKey": {
"asm": "0 cee9f88288a5f4980191a28d7ae08ff584050da7",
"hex": "0014cee9f88288a5f4980191a28d7ae08ff584050da7",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1qem5l3q5g5h6fsqv352xh4cy07kzq2rd8gphqma"
]
}
},
{
"value": 0.00999800,
"n": 1,
"scriptPubKey": {
"asm": "0 8d861ff6e8acf1ca2a3b3dd59c86f2e8a0aba75c",
"hex": "00148d861ff6e8acf1ca2a3b3dd59c86f2e8a0aba75c",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1q3krplahg4ncu523m8h2eephjazs2hf6ur8r6zp"
]
}
}
]
},
"unknown": {
},
"inputs": [
{
"witness_utxo": {
"amount": 0.01999800,
"scriptPubKey": {
"asm": "0 224cb503a7f7835799b9c22ee0c3c7d93d090356e30e70015c3ebbfa515a3074",
"hex": "0020224cb503a7f7835799b9c22ee0c3c7d93d090356e30e70015c3ebbfa515a3074",
"type": "witness_v0_scripthash",
"address": "tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0"
}
},
"partial_signatures": {
"038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e": "3044022040aae4f2ba37b1526524195f4a325d97d1317227b3c82aea55c5abd66810a7ec0220416e7c03e70a31232044addba454d6b37b6ace39ab163315d3293e343ae9513301",
"03789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd0636": "30440220327bd62b2f47659eeb29b5401c8b579490f971090f44803fbe9f7b5254e4f67f02207757b7a39761fef4b2d2eae6ea62bfdb48a7d17c4aaba761423084a3ad6199e901"
},
"witness_script": {
"asm": "2 038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e 03789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd0636 2 OP_CHECKMULTISIG",
"hex": "5221038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e2103789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd063652ae",
"type": "multisig"
},
"bip32_derivs": [
{
"pubkey": "03789f543423670e169667ff7e1f2da2a97df1b0912272e142d582451acebd0636",
"master_fingerprint": "be686772",
"path": "m"
},
{
"pubkey": "038d73adf2c7ea33f9dc34b77b62b59af433c1de9c763332da79e83e155f96030e",
"master_fingerprint": "d6043800",
"path": "m/0'/0'/26'"
}
]
}
],
"outputs": [
{
"bip32_derivs": [
{
"pubkey": "02fce26085452d07abc63bd389cb7dba9871e79bbecd08039291226be8232a9000",
"master_fingerprint": "d6043800",
"path": "m/0'/0'/24'"
}
]
},
{
"bip32_derivs": [
{
"pubkey": "0349cc43324f7ad94bb407a9bf12bc50afd9e7b430a472572f1b63cb555034f52a",
"master_fingerprint": "d3ed8825",
"path": "m/0'/0'/3'"
}
]
}
],
"fee": 0.00000200
}
$ bitcoin-cli analyzepsbt $psbt_c
{
"inputs": [
{
"has_utxo": true,
"is_final": false,
"next": "finalizer"
}
],
"estimated_vsize": 168,
"estimated_feerate": 0.00001190,
"fee": 0.00000200,
"next": "finalizer"
}
```
Funcionou! Acabamos de finalizar, enviar e pronto:
```
machine2$ psbt_c_hex=$(bitcoin-cli finalizepsbt $psbt_c | jq -r '.hex')
standup@btctest2:~$ bitcoin-cli -named sendrawtransaction hexstring=$psbt_c_hex
ee82d3e0d225e0fb919130d68c5052b6e3c362c866acc54d89af975330bb4d16
```
Obviamente, não houve uma grande melhoria no uso deste método em relação à assinatura em série de uma transação para um multisig 2-de-2 quando todos estavam usando o ```bitcoin-cli```: poderíamos ter passado uma transação bruta com assinaturas parciais de um usuário para o outro tão facilmente quanto enviar a PSBT. Mas, este foi o caso mais simples. À medida que nos aprofundamos em multisigs mais complexos, essa metodologia se torna cada vez melhor, mas já podemos destacar alguns pontos importantes:
Em primeiro lugar, é independente de plataforma. Enquanto todos estiverem usando um serviço compatível com o Bitcoin Core 0.17, todos poderão assinar essa transação, o que não é verdade quando os multisigs clássicos estão sendo repassados entre diferentes plataformas.
Em segundo lugar, é muito mais escalável. Considere um multisig 3-de-5. De acordo com a metodologia antiga, isso teria que ser transmitido de pessoa para pessoa, aumentando enormemente os problemas se alguém o corrompesse. Aqui, outros usuários precisam apenas enviar as PSBTs de volta ao Criador e, assim que tiver a quantidade suficiente, poderá gerar a transação final.
## Usando uma PSBT Para Financiamentos
Os Multisigs como o usado no exemplo anterior são frequentemente usados para receber pagamentos por trabalho colaborativo, seja royalties de um livro ou pagamentos feitos a uma empresa. Nessa situação, o exemplo acima funciona muito bem: os dois participantes recebem seu dinheiro, que depois é dividido. Mas e quanto ao caso inverso, em que dois (ou mais) participantes desejam criar uma _joint venture_ e precisam dividir o dinheiro?
A resposta tradicional é criar um multisig e depois fazer com que os participantes enviem individualmente os fundos para lá. O problema é que o primeiro pagador depende da boa fé do segundo, e isso não é a base do Bitcoin, que diz que _não devemos confiar_. Felizmente, com o advento das PSBTs, agora podemos fazer pagamentos sem confiança para podemos enviar fundos.
> :book: ***O que significa a ideia de não podermos confiar?*** Quando dizemos que não devemos confiar, significa que nenhum participante precisa confiar em nenhum outro participante. Ao invés disso, eles esperam que os protocolos de software garantam que tudo seja executado de maneira justa e esperada. O Bitcoin é um protocolo que não depende de confiança porque não precisamos que ninguém mais aja de boa fé. O sistema faz o gerenciamento. Da mesma forma, as PSBTs permitem a criação de transações que agrupam ou dividem fundos sem a necessidade de nenhuma parte confiar na outra.
O exemplo a seguir mostra dois usuários que possuem 0,010 BTC e que desejam agrupar no endereço multisig `tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0` criado acima.
```
machine1$ bitcoin-cli listunspent
[
{
"txid": "2536855bc8588e87206600cc980c30e8a65cf7f81002a34d6c37535e38a5b9db",
"vout": 0,
"address": "tb1qfg5y4fx979xkv4ezatc5eevufc8vh45553n4ut",
"label": "",
"scriptPubKey": "00144a284aa4c5f14d665722eaf14ce59c4e0ecbd694",
"amount": 0.01000000,
"confirmations": 2,
"spendable": true,
"solvable": true,
"desc": "wpkh([d6043800/0'/0'/25']02bea222cf9ea1f49b392103058cc7c8741d76a553fe627c1c43fc3ef4404c9d54)#4hnkg9ml",
"safe": true
}
]
machine2$ bitcoin-cli listunspent
[
{
"txid": "d7c7c24aeb1a61cdab81be6aefbf6c6a27562079629ffd9da4729bb82d93e4fe",
"vout": 0,
"address": "tb1qfqyyw6xrghm5kcrpkus3kl2l6dz4tpwrvn5ujs",
"label": "",
"scriptPubKey": "001448084768c345f74b6061b7211b7d5fd3455585c3",
"amount": 0.01000000,
"confirmations": 5363,
"spendable": true,
"solvable": true,
"desc": "wpkh([d3ed8825/0'/0'/0']03ff6b94c119582a63dbae4fb530efab0ed5635f7c3b2cf171264ca0af3ecef33a)#gtmd2e2k",
"safe": true
}
]
```
Eles configuram variáveis para usarem essas transações:
```
machine1$ utxo_txid_1=2536855bc8588e87206600cc980c30e8a65cf7f81002a34d6c37535e38a5b9db
machine1$ utxo_vout_1=0
machine1$ utxo_txid_2=d7c7c24aeb1a61cdab81be6aefbf6c6a27562079629ffd9da4729bb82d93e4fe
machine1$ utxo_vout_2=0
machine1$ multisig=tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0
```
E criam uma PSBT:
```
machine1$ psbt=$(bitcoin-cli -named createpsbt inputs='''[ { "txid": "'$utxo_txid_1'", "vout": '$utxo_vout_1' }, { "txid": "'$utxo_txid_2'", "vout": '$utxo_vout_2' } ]''' outputs='''{ "'$multisig'": 0.019998 }''')
```
O resultado fica mais ou menos assim:
```
machine1$ bitcoin-cli decodepsbt $psbt
{
"tx": {
"txid": "53ec62c5c2fe8b16ee2164e9699d16c7b8ac30ec53a696e55f09b79704b539b5",
"hash": "53ec62c5c2fe8b16ee2164e9699d16c7b8ac30ec53a696e55f09b79704b539b5",
"version": 2,
"size": 135,
"vsize": 135,
"weight": 540,
"locktime": 0,
"vin": [
{
"txid": "2536855bc8588e87206600cc980c30e8a65cf7f81002a34d6c37535e38a5b9db",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
},
{
"txid": "d7c7c24aeb1a61cdab81be6aefbf6c6a27562079629ffd9da4729bb82d93e4fe",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.01999800,
"n": 0,
"scriptPubKey": {
"asm": "0 224cb503a7f7835799b9c22ee0c3c7d93d090356e30e70015c3ebbfa515a3074",
"hex": "0020224cb503a7f7835799b9c22ee0c3c7d93d090356e30e70015c3ebbfa515a3074",
"reqSigs": 1,
"type": "witness_v0_scripthash",
"addresses": [
"tb1qyfxt2qa877p40xdecghwps78my7sjq6kuv88qq2u86al5526xp6qfqjud0"
]
}
}
]
},
"unknown": {
},
"inputs": [
{
},
{
}
],
"outputs": [
{
}
]
}
```
Não importa se as transações sejam de propriedade de duas pessoas diferentes ou que as informações completas apareçam em duas máquinas diferentes. Esta PSBT de financiamento funcionará exatamente da mesma forma que a PSBT multisig. Uma vez que todos os controladores tenham assinado, a transação pode ser finalizada.
Aqui está o processo, desta vez passando a PSBT parcialmente assinada de um usuário para outro, ao invés de ter que combinar as coisas no final.
```
machine1$ bitcoin-cli walletprocesspsbt $psbt
{
"psbt": "cHNidP8BAIcCAAAAAtu5pTheUzdsTaMCEPj3XKboMAyYzABmIIeOWMhbhTYlAAAAAAD//////uSTLbibcqSd/Z9ieSBWJ2psv+9qvoGrzWEa60rCx9cAAAAAAP////8BuIMeAAAAAAAiACAiTLUDp/eDV5m5wi7gw8fZPQkDVuMOcAFcPrv6UVowdAAAAAAAAQEfQEIPAAAAAAAWABRKKEqkxfFNZlci6vFM5ZxODsvWlAEIawJHMEQCIGAiKIAWRXiw68o3pw61/cVNP7n2oH73S654XXgQ4kjHAiBtTBqmaF1iIzYGXrG4DadH8y6mTuCRVFDiPl+TLQDBJwEhAr6iIs+eofSbOSEDBYzHyHQddqVT/mJ8HEP8PvRATJ1UAAABAUdSIQONc63yx+oz+dw0t3titZr0M8HenHYzMtp56D4VX5YDDiEDeJ9UNCNnDhaWZ/9+Hy2iqX3xsJEicuFC1YJFGs69BjZSriICA3ifVDQjZw4Wlmf/fh8toql98bCRInLhQtWCRRrOvQY2BL5oZ3IiAgONc63yx+oz+dw0t3titZr0M8HenHYzMtp56D4VX5YDDhDWBDgAAAAAgAAAAIAaAACAAA==",
"complete": false
}
machine2$ psbt_p="cHNidP8BAIcCAAAAAtu5pTheUzdsTaMCEPj3XKboMAyYzABmIIeOWMhbhTYlAAAAAAD//////uSTLbibcqSd/Z9ieSBWJ2psv+9qvoGrzWEa60rCx9cAAAAAAP////8BuIMeAAAAAAAiACAiTLUDp/eDV5m5wi7gw8fZPQkDVuMOcAFcPrv6UVowdAAAAAAAAQEfQEIPAAAAAAAWABRKKEqkxfFNZlci6vFM5ZxODsvWlAEIawJHMEQCIGAiKIAWRXiw68o3pw61/cVNP7n2oH73S654XXgQ4kjHAiBtTBqmaF1iIzYGXrG4DadH8y6mTuCRVFDiPl+TLQDBJwEhAr6iIs+eofSbOSEDBYzHyHQddqVT/mJ8HEP8PvRATJ1UAAABAUdSIQONc63yx+oz+dw0t3titZr0M8HenHYzMtp56D4VX5YDDiEDeJ9UNCNnDhaWZ/9+Hy2iqX3xsJEicuFC1YJFGs69BjZSriICA3ifVDQjZw4Wlmf/fh8toql98bCRInLhQtWCRRrOvQY2BL5oZ3IiAgONc63yx+oz+dw0t3titZr0M8HenHYzMtp56D4VX5YDDhDWBDgAAAAAgAAAAIAaAACAAA=="
machine2$ psbt_f=$(bitcoin-cli walletprocesspsbt $psbt_p | jq -r '.psbt')
machine2$ bitcoin-cli analyzepsbt $psbt_f
{
"inputs": [
{
"has_utxo": true,
"is_final": true,
"next": "extractor"
},
{
"has_utxo": true,
"is_final": true,
"next": "extractor"
}
],
"estimated_vsize": 189,
"estimated_feerate": 0.00001058,
"fee": 0.00000200,
"next": "extractor"
}
machine2$ psbt_hex=$(bitcoin-cli finalizepsbt $psbt_f | jq -r '.hex')
machine2$ bitcoin-cli -named sendrawtransaction hexstring=$psbt_hex
53ec62c5c2fe8b16ee2164e9699d16c7b8ac30ec53a696e55f09b79704b539b5
```
Usamos uma PSBT para reunir o dinheiro usando um multisig sem precisar de confiança!
## Usando uma PSBT para CoinJoin
O CoinJoin é outra aplicação no Bitcoin que não requer confiança. Aqui, temos uma variedade de entes que não se conhecem juntando dinheiro e recebendo de volta.
A metodologia para gerenciá-lo com PSBTs é exatamente a mesma que vimos nos exemplos acima, como o seguinte pseudocódigo demonstra:
```
$ psbt=$(bitcoin-cli -named createpsbt inputs='''[ { "txid": "'$utxo_txid_1'", "vout": '$utxo_vout_1' }, { "txid": "'$utxo_txid_2'", "vout": '$utxo_vout_2' }, { "txid": "'$utxo_txid_3'", "vout": '$utxo_vout_3' } ]''' outputs='''{ "'$split1'": 1.7,"'$split2'": 0.93,"'$split3'": 1.4 }''')
```
Cada usuário coloca o próprio UTXO e cada um recebe uma saída correspondente.
A melhor maneira de gerenciar um CoinJoin é enviar a PSBT básica para todas as partes (que podem ser inúmeras) e, em seguida, fazer com que cada uma assine a PSBT e envie de volta para uma única parte que irá combinar, finalizar e enviar.
## Resumo: Usando uma Transação Parcialmente Assinada no Bitcoin (PSBT)
Agora vimos o processo PSBT que aprendemos na seção [§7.1](07_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md) em uso em três exemplos da vida real: criando um multisig, um financiamento e fazendo CoinJoin. Tudo isso era teoricamente possível no Bitcoin com várias pessoas assinando transações cuidadosamente construídas, mas as PSBTs tornam isso padronizado e simples.
> :fire: ***Qual é o poder de uma PSBT?*** Uma PSBT permite a criação de transações sem necessidade de confiança entre várias partes e várias máquinas. Se mais de uma parte precisar financiar uma transação, se mais de uma parte precisar assinar uma transação, ou se uma transação precisar ser criada em uma máquina e assinada em outra, uma PSBT torna isso simples, sem depender do mecanismos de assinatura parcial não padronizados que existiam antes da PSBT.
Esse último ponto, sobre criar uma transação em uma máquina e assinar em outra, é um elemento das PSBTs ao qual ainda não chegamos. Ele está no centro das carteiras de hardware, onde geralmente desejamos criar uma transação em um full node e, em seguida, passá-la para uma hardware wallet quando uma assinatura for necessária. Esse é o tópico da nossa última seção (e do nosso quarto exemplo da vida real) deste capítulo sobre PSBTs.
## O Que Vem Depois?
Vamos continuar "Expandindo Transações no Bitcoin com PSBTs" na seção [§7.3: Integrando com Hardware Wallets](07_3_Integrating_with_Hardware_Wallets.md).

View File

@ -0,0 +1,469 @@
# 7.3: Integrando com Hardware Wallets
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. Leitor de advertência.
Uma das principais vantagens das PSBTs é a capacidade de transferir transações para hardware wallets. Esta será uma ótima ferramenta de desenvolvimento para nós continuarmos a programar com Bitcoin. No entanto, não podemos testá-la agora se estivermos usando uma das configurações que sugerimos para este curso, uma VM no Linode de acordo com a seção [§2.1](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md) ou uma opção mais expansiva ainda como um AWS de acordo com a seção [§2.2](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/02_2_Setting_Up_Bitcoin_Core_Other.md), isso porque obviamente não teremos como conectar uma hardware wallet à nossa máquina virtual remota.
> :book: ***O que é uma hardware wallet?*** Uma hardware wallet é um dispositivo eletrônico que melhora a segurança da criptomoeda mantendo todas as chaves privadas no dispositivo, ao invés de colocá-las em um computador conectado diretamente a internet. As hardware wallets têm protocolos específicos para fornecer interações online, geralmente gerenciadas por um programa que se comunica com o dispositivo por meio de uma porta USB. Neste capítulo, gerenciaremos uma hardware wallet com o ```bitcoin-cli``` e o programa ```hwy.py```.
Existem três opções de como passar por este capítulo: (1) ler sem testar o código; (2) instalar o Bitcoin em uma máquina local para testar todos esses comandos ou; (3) pular direto para o [Capítulo 8: Expandindo Transações no Bitcoin de Outras Maneiras](08_0_Expanding_Bitcoin_Transactions_Other.md). Sugerimos a primeira opção, mas se quisermos colocar a mão na massa, iremos dar o suporte necessário para a segunda opção falando sobre o uso de um Macintosh (uma plataforma hardware que o [Bitcoin Standup](https://github.com/BlockchainCommons/Bitcoin-Standup) dá suporte) para teste.
> :warning: **AVISO DE VERSÃO:** As PSBTs são uma inovação do Bitcoin Core v0.17.0. As versões anteriores do Bitcoin Core não funcionarão com o PSBT enquanto ele estiver em andamento (embora ainda consigam reconhecer a transação final). A interface HWI apareceu no Bitcoin Core v 0.18.0, mas, desde que estejamos usando nossa configuração sugerida com o Bitcoin Standup, ela deve funcionar.
A metodologia descrita neste capítulo para integração com uma hardware wallet depende do [Bitcoin Hardware Wallet Interface](https://github.com/bitcoin-core/HWI) lançada através do Bitcoin Core e que se baseia nas instruções de [instalação](https://github.com/bitcoin-core/HWI/blob/master/README.md) e [uso](https://hwi.readthedocs.io) contidas nele.
> :warning: **AVISO DE NOVIDADE:** A interface HWI é muito nova e precisa de alguns ajustes ainda, mesmo na v0.20.0 do Bitcoin Core. Pode ser difícil instalá-la corretamente e pode conter erros não intuitivos. O que segue é uma descrição de uma configuração que funciona, mas foram necessárias várias tentativas para ter sucesso e sua configuração pode variar.
## Instalando o Bitcoin Core em uma Máquina Local
_Se pretendemos apenas ler esta seção e não testar os comandos, podemos pular esta subseção, que basicamente explicará como criar uma instalação Bitcoin Core em uma máquina local, como uma máquina Mac ou Linux._
Existem versões alternativas do script Bitcoin Standup que usamos para criar nossa VM que será instalada em um MacOS ou em uma máquina Linux que não seja o Linode.
Se tivermos MacOS, podemos instalar o [Bitcoin Standup MacOS](https://github.com/BlockchainCommons/Bitcoin-Standup-MacOS/blob/master/README.md).
Se tivermos uma máquina Linux local, podemos instalar o [Bitcoin Standup Linux Scripts](https://github.com/BlockchainCommons/Bitcoin-Standup-MacOS/blob/master/README.md).
Depois de colocar o Bitcoin Standup em execução em nossa máquina local, vamos desejar sincronizar o blockchain "Testnet", assumindo que já estamos seguindo o método padrão deste curso.
Estaremos usando um Macintosh e um Testnet para os exemplos desta seção.
### Criando um Alias para o Bitcoin-CLI
Crie um alias que execute o ```bitcoin-cli``` no diretório correto com quaisquer flags apropriadas.
Aqui está um exemplo de um alias de um Mac:
```
$ alias bitcoin-cli="~/StandUp/BitcoinCore/bitcoin-0.20.0/bin/bitcoin-cli -testnet"
```
Podemos notar que ele nos dá não apenas o caminho completo, mas também garante que permaneçamos na Testnet.
## Instalando o HWI em uma Máquina Local
_As instruções a seguir novamente presumem um Mac e podemos pular novamente esta subseção se estivermos apenas lendo o capítulo._
O HWI é um programa do Bitcoin Core disponível em python que podemos usar para interagir com as hardware wallets.
### Instalando Python
Como o HWI é escrito em ```python```, precisaremos instalá-lo, bem como alguns programas auxiliares.
Se ainda não temos as ferramentas de linha de comando ```xcode```, iremos precisar delas:
```
$ xcode-select --install
```
Se ainda não temos o gerenciador de pacotes Homebrew, precisamos instalá-lo também. As instruções atuais estão disponíveis no [site do Homebrew](https://brew.sh/). No momento em que este livro foi escrito, basta utilizarmos o comando abaixo:
```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```
Para uma instalação pela primeira vez, também devemos nos certificar de que nosso diretório ```/usr/local/Frameworks``` foi criado corretamente:
```
$ sudo mkdir /usr/local/Frameworks
$ sudo chown $(whoami):admin /usr/local/Frameworks
```
Se já fizemos tudo isso, podemos finalmente instalar o Python:
```
$ brew install python
$ brew install libusb
```
### Instalando o HWI
Agora estamos prontos para instalar o HWI, o que requer a clonagem de um repositório GitHub e a execução de um script de instalação.
Se ainda não temos o ```git``` instalado em nosso Mac, podemos fazer isso apenas executando o comando: ```git --version```.
Podemos então clonar o repositório HWI:
```
$ cd ~/StandUp
$ git clone https://github.com/bitcoin-core/HWI.git
```
Depois, precisaremos instalar o pacote e as dependências:
```
$ cd HWI
HWI$ python3 setup.py install
```
### Criando um Alias para o HWI
Iremos querer criar um alias aqui também, variando de acordo com o local de instalação real:
```
$ alias hwi="~/Standup/HWI/hwi.py --testnet"
```
Novamente, incluímos uma referência a testnet no alias.
## Preparando nossa Ledger
_Tivemos que escolher uma plataforma de hardware wallet para a demonstração de HWI. Nossa escolha foi a Ledger, que há muito tempo é onde fazemos os testes nestes casos. Podemos consultar as [informações de suporte do dispositivo do HWI](https://github.com/bitcoin-core/HWI/blob/master/README.md#device-support) para obter uma lista de outros dispositivos compatíveis. Se usarmos um dispositivo diferente de uma Ledger, precisaremos avaliar as nossas soluções para prepará-la para uso na Testnet, mas caso contrário, devemos ser capazes de continuar com o curso conforme escrito aqui._
Se estiver trabalhando com Bitcoins usando a Ledger, provavelmente não precisaremos fazer nada. (Mas não sugerimos isso neste curso).
Para trabalhar com moedas da Testnet, conforme sugerido aqui, precisaremos fazer algumas atualizações:
1. Vamos em Configurações em nosso aplicativo Ledger Live (clicando na engrenagem), depois na guia "Recursos Experimentais" e vamos ativar o "Modo de Desenvolvedor";
2. Vamos no "Gerenciar" para instalar o "Bitcoin Test". A versão atual requer que tenhamos o "Bitcoin" e o "Ethereum" instalados primeiro;
3. Vamos ao "Gerenciar", para instalar o nosso novo "Bitcoin Test" e "Adicionar uma conta".
## Acoplando a Ledger
Para que uma Ledger esteja acessível, devemos fazer o login com o nosso PIN e, em seguida, acessar o aplicativo que desejamos usar, que no caso é o aplicativo "Bitcoin Test". Pode ser necessário repetir isso algumas vezes quando nossa Ledger ficar em stand-by.
Depois, podemos solicitar que o HWI acesse a Ledger com o comando `enumerate`:
```
$ hwi enumerate
[{"type": "ledger", "model": "ledger_nano_s", "path": "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14100000/Nano S@14100000/Nano S@0/IOUSBHostHIDDevice@14100000,0", "fingerprint": "9a1d520b", "needs_pin_sent": false, "needs_passphrase_sent": false}]
```
Se recebermos algumas informações no nosso dispositivo, está tudo certo! Como podemos observar, ele verifica o tipo da hardware wallet, fornecendo outras informações de identificação e também informa como se comunicar com o dispositivo. A ```fingerprint``` (```9a1d520b```) é o que devemos prestar atenção especial, porque todas as interações com nossa hardware wallet irão exigir essa informação.
Se, ao invés disso, obtivermos como resultado ```[ ]```, então ou (1) não deixamos nosso dispositivo Ledger habilitado com o PIN correto e não escolhemos o aplicativo correto, ou (2) há algo de errado com nossa configuração Python, provavelmente uma dependência esteja faltando: devemos considerar usar o comando ```uninstall``` e tentar do zero novamente.
## Importando Endereços
A interação com uma hardware wallet geralmente ocorre em duas partes: observando os saldos e gastando-os.
Podemos monitorar os fundos importando os endereços da nossa hardware wallet para o full node, usando o HWI e o ```bitcoin-cli```.
### Criando uma Carteira
Para usar nossa hardware wallet com o ```bitcoin-cli```, precisaremos criar uma carteira com nome específico no Bitcoin Core, usando o RPC ```createwallet```, que é um comando que não discutimos anteriormente.
```
$ bitcoin-cli --named createwallet wallet_name="ledger" disable_private_keys="true"
{
"name": "ledger",
"warning": ""
}
```
Neste caso, estamos criando uma carteira chamada `ledger` sem chaves privadas (já que estas estarão no dispositivo Ledger).
> :book: ***Por que nomear as carteiras?*** Até agora, este curso usou uma carteira padrão ("") no Bitcoin Core. Isso é bom para muitos propósitos, mas é inadequado se tivermos uma situação mais complexa, como quando estamos usando as chaves de uma hardware wallet. Aqui, queremos ser capazes de diferenciar as chaves locais (que são mantidas na carteira "") e as chaves da Ledger (que são mantidas na carteira "ledger").
Agora podemos observar que a nova carteira está em nossa lista de carteiras:
```
$ bitcoin-cli listwallets
[
"",
"ledger"
]
```
Como criamos uma segunda carteira, alguns comandos exigirão um sinalizador ```-rpcwallet=```, para especificar qual delas estamos utilizando.
### Importando as Chaves
Agora temos que importar uma lista de observação de endereços da hardware wallet. Isso é feito com o comando ```getkeypool``` do HWI:
```
$ hwi -f 9a1d520b getkeypool --wpkh 0 1000
[{"desc": "wpkh([9a1d520b/84h/1h/0h]tpubDD7KTtoGzK9GuWUQcr1uTJazsAkqoXhdrwGXWVix6nPpNZmSbagZWD4QSaMsyK8YohAirGDPrWdRiEpKzTFB7DrTrqfzHCn7yi5EsqeR93S/0/*)#qttxy592", "range": [0, 1000], "timestamp": "now", "internal": false, "keypool": true, "active": true, "watchonly": true}, {"desc": "wpkh([9a1d520b/84h/1h/0h]tpubDD7KTtoGzK9GuWUQcr1uTJazsAkqoXhdrwGXWVix6nPpNZmSbagZWD4QSaMsyK8YohAirGDPrWdRiEpKzTFB7DrTrqfzHCn7yi5EsqeR93S/1/*)#3lw8ep4j", "range": [0, 1000], "timestamp": "now", "internal": true, "keypool": true, "active": true, "watchonly": true}]
```
Endereçamos o HWI com a ```fingerprint``` e solicitamos os primeiros 1000 endereços WPKH (Segwit nativo). Em troca, recebemos dois descritores para o conjunto de chaves: um para receber endereços e outro para alterar endereços.
> :book: ***O que é um conjunto de chaves?*** Um conjunto de chaves é um grupo de chaves pré-geradas. As hardware wallets modernas criam molhos de chaves usando novos endereços hierárquicos com base na seed original. A ideia destes molhos de chaves é facilitar os requisitos de backup das carteiras. Isso permitia que um usuário gerasse um conjunto de chaves e fizesse backup da carteira imediatamente, ao invés de exigir backups após a criação de cada novo endereço. O conceito também tem se mostrado muito útil na atualidade, pois permite a importação de todo um conjunto de endereços de um dispositivo para outro.
Os valores retornados pelo comando ```getkeypool``` são os mesmos tipos de descritores que aprendemos na seção [§3.5: Compreendendo o Descritor](03_5_Understanding_the_Descriptor.md). Na época, dissemos que eram úteis para mover endereços entre máquinas diferentes. Aqui está o exemplo da vida real: mover endereços de uma hardware wallet para o node do Bitcoin Core, de modo que nossa máquina conectada à rede possa vigiar as chaves pertencentes à carteira da hardware wallet.
Assim como aprendemos na seção [§3.5](03_5_Understanding_the_Descriptor.md), podemos examinar esses descritores com o comando RPC ```getdescriptorinfo```:
```
$ bitcoin-cli getdescriptorinfo "wpkh([9a1d520b/84h/1h/0h]tpubDD7KTtoGzK9GuWUQcr1uTJazsAkqoXhdrwGXWVix6nPpNZmSbagZWD4QSaMsyK8YohAirGDPrWdRiEpKzTFB7DrTrqfzHCn7yi5EsqeR93S/0/*)#qttxy592"
{
"descriptor": "wpkh([9a1d520b/84'/1'/0']tpubDD7KTtoGzK9GuWUQcr1uTJazsAkqoXhdrwGXWVix6nPpNZmSbagZWD4QSaMsyK8YohAirGDPrWdRiEpKzTFB7DrTrqfzHCn7yi5EsqeR93S/0/*)#n65e7wjf",
"checksum": "qttxy592",
"isrange": true,
"issolvable": true,
"hasprivatekeys": false
}
```
Como era de se esperar, _não_ temos ```privatekeys```, porque as hardware wallets as mantém.
Com os descritores em mãos, podemos importar as chaves para nossa nova carteira ```ledger``` usando o comando RPC ```importmulti``` que já usamos na seção [§3.5](03_5_Understanding_the_Descriptor.md). Nesse caso, basta colocar toda a resposta que recebemos do HWI entre ```'``` s.
```
$ bitcoin-cli -rpcwallet=ledger importmulti '[{"desc": "wpkh([9a1d520b/84h/1h/0h]tpubDD7KTtoGzK9GuWUQcr1uTJazsAkqoXhdrwGXWVix6nPpNZmSbagZWD4QSaMsyK8YohAirGDPrWdRiEpKzTFB7DrTrqfzHCn7yi5EsqeR93S/0/*)#qttxy592", "range": [0, 1000], "timestamp": "now", "internal": false, "keypool": true, "active": true, "watchonly": true}, {"desc": "wpkh([9a1d520b/84h/1h/0h]tpubDD7KTtoGzK9GuWUQcr1uTJazsAkqoXhdrwGXWVix6nPpNZmSbagZWD4QSaMsyK8YohAirGDPrWdRiEpKzTFB7DrTrqfzHCn7yi5EsqeR93S/1/*)#3lw8ep4j", "range": [0, 1000], "timestamp": "now", "internal": true, "keypool": true, "active": true, "watchonly": true}]'
[
{
"success": true
},
{
"success": true
}
]
```
(Observe que HWI aproveita o caminho de derivação com ```h```s para mostrar as derivações ao invés dos ```'```s, além de ter calculado a soma da verificação corretamente, para que não tenhamos que fazer citações massivas como fizemos na seção §3.5.)
Agora, _poderíamos_ listar todos os endereços apenas para observar que recebemos o valor, usando o comando ```getaddressesbylabel```. Todos os 1000 endereços de recebimento estão ali, na carteira ```ledger```!
```
$ bitcoin-cli -rpcwallet=ledger getaddressesbylabel "" | more
{
"tb1qqqvnezljtmc9d7x52udpc0m9zgl9leugd2ur7y": {
"purpose": "receive"
},
"tb1qqzvrm6hujdt93qctuuev5qc4499tq9fdk0prwf": {
"purpose": "receive"
},
...
}
```
## Recebendo uma Transação
Obviamente, receber uma transação é bem simples. Usamos o ```getnewaddress``` para solicitar um daqueles endereços importados:
```
$ bitcoin-cli -rpcwallet=ledger getnewaddress
tb1qqqvnezljtmc9d7x52udpc0m9zgl9leugd2ur7y
```
Então enviamos o dinheiro para ele.
O poder do HWI é que podemos observar os pagamentos do nosso node Bitcoin Core, ao invés de termos que conectar nossa hardware wallet e consultá-la.
```
$ bitcoin-cli -rpcwallet=ledger listunspent
[
{
"txid": "c733533eb1c052242f9ed89cd8927aedb41852156e684634ee7c74028774e595",
"vout": 1,
"address": "tb1q948388a23pfsf52kz6skd5k4z4627jja2evztr",
"label": "",
"scriptPubKey": "00142d4f139faa885304d15616a166d2d51574af4a5d",
"amount": 0.01000000,
"confirmations": 12,
"spendable": false,
"solvable": true,
"desc": "wpkh([9a1d520b/84'/1'/0'/0/0]02a013cf9c4b5f5689d9253036a3e477cf98689626f7814c94f092726f11b741ab)#9za8hlvk",
"safe": true
},
{
"txid": "5b3c4aeb811f9a119fd633b12a6927415cc61b8654628df58e9141cab804bab8",
"vout": 0,
"address": "tb1qqqvnezljtmc9d7x52udpc0m9zgl9leugd2ur7y",
"label": "",
"scriptPubKey": "001400193c8bf25ef056f8d4571a1c3f65123e5fe788",
"amount": 0.01000000,
"confirmations": 1,
"spendable": false,
"solvable": true,
"desc": "wpkh([9a1d520b/84'/1'/0'/0/569]030168d9482e2b02d7027fb4a89edc54adaa1adf709334f647d0a1b0533828aec5)#sx9haake",
"safe": true
}
]
```
## Criando uma Transação com PSBT
Observar e receber pagamentos é apenas metade da batalha. Também podemos fazer pagamentos usando contas mantidas em nossa hardware wallet. Este é o quarto exemplo da vida real usando as PSBTs, de acordo com o processo descrito na seção [§7.1: Criando uma Transação Bitcoin Parcialmente Assinada](7_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md).
Os comandos funcionam exatamente da mesma forma. Nesse caso, usamos o ```walletcreatefundedpsbt``` para formar nossa PSBT porque estamos em uma situação em que não nos importamos com quais UTXOs são usados:
```
$ bitcoin-cli -named -rpcwallet=ledger walletcreatefundedpsbt inputs='''[]''' outputs='''[{"tb1qcaedd724gts3aug73m78c7nfsv9d8zs9q6h2kd":0.015}]'''
{
"psbt": "cHNidP8BAJoCAAAAAri6BLjKQZGO9Y1iVIYbxlxBJ2kqsTPWnxGaH4HrSjxbAAAAAAD+////leV0hwJ0fO40RmhuFVIYtO16ktic2J4vJFLAsT5TM8cBAAAAAP7///8CYOMWAAAAAAAWABTHctb5VULhHvEejvx8emmDCtOKBU+gBwAAAAAAFgAU9Ojd5ds3CJi1fIRWbj92CYhQgX0AAAAAAAEBH0BCDwAAAAAAFgAUABk8i/Je8Fb41FcaHD9lEj5f54giBgMBaNlILisC1wJ/tKie3FStqhrfcJM09kfQobBTOCiuxRiaHVILVAAAgAEAAIAAAACAAAAAADkCAAAAAQEfQEIPAAAAAAAWABQtTxOfqohTBNFWFqFm0tUVdK9KXSIGAqATz5xLX1aJ2SUwNqPkd8+YaJYm94FMlPCScm8Rt0GrGJodUgtUAACAAQAAgAAAAIAAAAAAAAAAAAAAIgID2UK1nupSfXC81nmB65XZ+pYlJp/W6wNk5FLt5ZCSx6kYmh1SC1QAAIABAACAAAAAgAEAAAABAAAAAA==",
"fee": 0.00000209,
"changepos": 1
}
```
Podemos observar a PSBT e verificar se ela parece correta:
```
$ psbt="cHNidP8BAJoCAAAAAri6BLjKQZGO9Y1iVIYbxlxBJ2kqsTPWnxGaH4HrSjxbAAAAAAD+////leV0hwJ0fO40RmhuFVIYtO16ktic2J4vJFLAsT5TM8cBAAAAAP7///8CYOMWAAAAAAAWABTHctb5VULhHvEejvx8emmDCtOKBU+gBwAAAAAAFgAU9Ojd5ds3CJi1fIRWbj92CYhQgX0AAAAAAAEBH0BCDwAAAAAAFgAUABk8i/Je8Fb41FcaHD9lEj5f54giBgMBaNlILisC1wJ/tKie3FStqhrfcJM09kfQobBTOCiuxRiaHVILVAAAgAEAAIAAAACAAAAAADkCAAAAAQEfQEIPAAAAAAAWABQtTxOfqohTBNFWFqFm0tUVdK9KXSIGAqATz5xLX1aJ2SUwNqPkd8+YaJYm94FMlPCScm8Rt0GrGJodUgtUAACAAQAAgAAAAIAAAAAAAAAAAAAAIgID2UK1nupSfXC81nmB65XZ+pYlJp/W6wNk5FLt5ZCSx6kYmh1SC1QAAIABAACAAAAAgAEAAAABAAAAAA=="
$ 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
}
```
E, como de costume, `analisepsbt` mostrará o quão longe você chegou:
```
$ bitcoin-cli analyzepsbt $psbt
{
"inputs": [
{
"has_utxo": true,
"is_final": false,
"next": "signer",
"missing": {
"signatures": [
"00193c8bf25ef056f8d4571a1c3f65123e5fe788"
]
}
},
{
"has_utxo": true,
"is_final": false,
"next": "signer",
"missing": {
"signatures": [
"2d4f139faa885304d15616a166d2d51574af4a5d"
]
}
}
],
"estimated_vsize": 208,
"estimated_feerate": 0.00001004,
"fee": 0.00000209,
"next": "signer"
}
```
Como importamos aquele conjunto de chaves, o ```bitcoin-cli``` tem todas as informações de que precisa para preencher as entradas, porém, ele não pode assinar porque as chaves privadas são mantidas na hardware wallet.
É aí que entra o HWI, com o comando ```signtx```. Basta que enviemos a PSBT junto:
```
$ hwi -f 9a1d520b signtx $psbt
```
É provável que tenhamos de mexer em nossa hardware wallet neste momento. O dispositivo provavelmente pedirá a confirmação das entradas, as saídas e a taxa. Quando terminar, ele deve retornar uma nova PSBT.
```
{"psbt": "cHNidP8BAJoCAAAAAri6BLjKQZGO9Y1iVIYbxlxBJ2kqsTPWnxGaH4HrSjxbAAAAAAD+////leV0hwJ0fO40RmhuFVIYtO16ktic2J4vJFLAsT5TM8cBAAAAAP7///8CYOMWAAAAAAAWABTHctb5VULhHvEejvx8emmDCtOKBU+gBwAAAAAAFgAU9Ojd5ds3CJi1fIRWbj92CYhQgX0AAAAAAAEBH0BCDwAAAAAAFgAUABk8i/Je8Fb41FcaHD9lEj5f54giAgMBaNlILisC1wJ/tKie3FStqhrfcJM09kfQobBTOCiuxUcwRAIgAxkQlk2fqEMxvP54WWyiFhlfSul9sd4GzKDhfGpmlewCIHYej3zXWWMgWI6rixxQw9yzGozDaFPqQNNIvcFPk+lfASIGAwFo2UguKwLXAn+0qJ7cVK2qGt9wkzT2R9ChsFM4KK7FGJodUgtUAACAAQAAgAAAAIAAAAAAOQIAAAABAR9AQg8AAAAAABYAFC1PE5+qiFME0VYWoWbS1RV0r0pdIgICoBPPnEtfVonZJTA2o+R3z5holib3gUyU8JJybxG3QatHMEQCIH5t6T2yufUP7glYZ8YH0/PhDFpotSmjgZUhvj6GbCFIAiBcgXzyYl7IjYuaF3pJ7AgW1rLYkjeCJJ2M9pVUrq5vFwEiBgKgE8+cS19WidklMDaj5HfPmGiWJveBTJTwknJvEbdBqxiaHVILVAAAgAEAAIAAAACAAAAAAAAAAAAAACICA9lCtZ7qUn1wvNZ5geuV2fqWJSaf1usDZORS7eWQksepGJodUgtUAACAAQAAgAAAAIABAAAAAQAAAAA="}
$ psbt_f="cHNidP8BAJoCAAAAAri6BLjKQZGO9Y1iVIYbxlxBJ2kqsTPWnxGaH4HrSjxbAAAAAAD+////leV0hwJ0fO40RmhuFVIYtO16ktic2J4vJFLAsT5TM8cBAAAAAP7///8CYOMWAAAAAAAWABTHctb5VULhHvEejvx8emmDCtOKBU+gBwAAAAAAFgAU9Ojd5ds3CJi1fIRWbj92CYhQgX0AAAAAAAEBH0BCDwAAAAAAFgAUABk8i/Je8Fb41FcaHD9lEj5f54giAgMBaNlILisC1wJ/tKie3FStqhrfcJM09kfQobBTOCiuxUcwRAIgAxkQlk2fqEMxvP54WWyiFhlfSul9sd4GzKDhfGpmlewCIHYej3zXWWMgWI6rixxQw9yzGozDaFPqQNNIvcFPk+lfASIGAwFo2UguKwLXAn+0qJ7cVK2qGt9wkzT2R9ChsFM4KK7FGJodUgtUAACAAQAAgAAAAIAAAAAAOQIAAAABAR9AQg8AAAAAABYAFC1PE5+qiFME0VYWoWbS1RV0r0pdIgICoBPPnEtfVonZJTA2o+R3z5holib3gUyU8JJybxG3QatHMEQCIH5t6T2yufUP7glYZ8YH0/PhDFpotSmjgZUhvj6GbCFIAiBcgXzyYl7IjYuaF3pJ7AgW1rLYkjeCJJ2M9pVUrq5vFwEiBgKgE8+cS19WidklMDaj5HfPmGiWJveBTJTwknJvEbdBqxiaHVILVAAAgAEAAIAAAACAAAAAAAAAAAAAACICA9lCtZ7qUn1wvNZ5geuV2fqWJSaf1usDZORS7eWQksepGJodUgtUAACAAQAAgAAAAIABAAAAAQAAAAA="
```
Ao analisá-la, veremos que estamos prontos para finalizá-la:
```
$ bitcoin-cli analyzepsbt $psbt_f
{
"inputs": [
{
"has_utxo": true,
"is_final": false,
"next": "finalizer"
},
{
"has_utxo": true,
"is_final": false,
"next": "finalizer"
}
],
"estimated_vsize": 208,
"estimated_feerate": 0.00001004,
"fee": 0.00000209,
"next": "finalizer"
}
```
Neste momento, estamos de volta a terras já conhecidas:
```
$ bitcoin-cli finalizepsbt $psbt_f
{
"hex": "02000000000102b8ba04b8ca41918ef58d6254861bc65c4127692ab133d69f119a1f81eb4a3c5b0000000000feffffff95e5748702747cee3446686e155218b4ed7a92d89cd89e2f2452c0b13e5333c70100000000feffffff0260e3160000000000160014c772d6f95542e11ef11e8efc7c7a69830ad38a054fa0070000000000160014f4e8dde5db370898b57c84566e3f76098850817d024730440220031910964d9fa84331bcfe78596ca216195f4ae97db1de06cca0e17c6a6695ec0220761e8f7cd7596320588eab8b1c50c3dcb31a8cc36853ea40d348bdc14f93e95f0121030168d9482e2b02d7027fb4a89edc54adaa1adf709334f647d0a1b0533828aec50247304402207e6de93db2b9f50fee095867c607d3f3e10c5a68b529a3819521be3e866c214802205c817cf2625ec88d8b9a177a49ec0816d6b2d8923782249d8cf69554aeae6f17012102a013cf9c4b5f5689d9253036a3e477cf98689626f7814c94f092726f11b741ab00000000",
"complete": true
}
$ hex=02000000000102b8ba04b8ca41918ef58d6254861bc65c4127692ab133d69f119a1f81eb4a3c5b0000000000feffffff95e5748702747cee3446686e155218b4ed7a92d89cd89e2f2452c0b13e5333c70100000000feffffff0260e3160000000000160014c772d6f95542e11ef11e8efc7c7a69830ad38a054fa0070000000000160014f4e8dde5db370898b57c84566e3f76098850817d024730440220031910964d9fa84331bcfe78596ca216195f4ae97db1de06cca0e17c6a6695ec0220761e8f7cd7596320588eab8b1c50c3dcb31a8cc36853ea40d348bdc14f93e95f0121030168d9482e2b02d7027fb4a89edc54adaa1adf709334f647d0a1b0533828aec50247304402207e6de93db2b9f50fee095867c607d3f3e10c5a68b529a3819521be3e866c214802205c817cf2625ec88d8b9a177a49ec0816d6b2d8923782249d8cf69554aeae6f17012102a013cf9c4b5f5689d9253036a3e477cf98689626f7814c94f092726f11b741ab00000000
$ bitcoin-cli sendrawtransaction $hex
45f996d4ff8c9e9ab162f611c5b6ad752479ede9780f9903bdc80cd96619676d
```
Pronto, enviamos um saldo com sucesso usando as chaves privadas de nossa hardware wallet!
## Aprendendo Outros Comandos HWI
Existem vários outros comandos disponíveis para usar com o HWI. No momento em que este artigo foi escrito, são eles:
```
numerate,getmasterxpub,signtx,getxpub,signmessage,getkeypool,getdescriptors,displayaddress,setup,wipe,restore,backup,promptpin,togglepassphrase,sendpin
```
## Resumo: Integrando com Hardware Wallets
As hardware wallets podem oferecer melhor proteção, mantendo nossas chaves privadas offline, protegidas no hardware. Felizmente, ainda há uma maneira de interagir com elas usando o ```bitcoin-cli```. Basta instalar o HWI e ele permitirá (1) importar as chaves públicas para observarmos; e (2) assinar transações usando nossa hardware wallet.
> :fire: ***Qual é o poder do HWI?*** O HWI nos permite interagir com hardware wallets usando todos os comandos do ```bitcoin-cli``` que aprendemos até agora. Podemos fazer transações brutas de qualquer tipo e enviar PSBTs para hardware wallets para serem assinadas. Assim, temos todo o poder do Bitcoin Core, mas também temos a segurança de um dispositivo hardware.
## O Que Vem Depois?
Vamos expandir ainda mais as transações de Bitcoin com o [Capítulo Oito: Expandindo Transações no Bitcoin de Outras Maneiras](08_0_Expanding_Bitcoin_Transactions_Other.md).

View File

@ -0,0 +1,21 @@
# Capítulo 8: Expandindo Transações no Bitcoin de Outras Maneiras
A definição de transações básicas descrita no [Capítulo Seis](06_0_Expanding_Bitcoin_Transactions_Multisigs.md) diz que enviamos os _fundos_ _imediatamente_, mas esses são os dois elementos que podem ser alterados. Esta seção final sobre _Expandindo transações de Bitcoin_ fala sobre como enviar coisas que não sejam moedas e como fazer isso em um momento diferente do atual.
## Objetivos deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Criar transações com Locktimes;
* Criar transações com dados.
Os objetivos secundários incluem a capacidade de:
* Compreender os diferentes tipos de Timelocks;
* Planejar usando o poder do Locktime;
* Planejar usando o poder de OP_RETURN.
## Tabela de Conteúdo
* [Seção Um: Enviando uma Transação com um Locktime](08_1_Sending_a_Transaction_with_a_Locktime.md)
* [Seção Dois: Enviando uma Transação com Dados](08_2_Sending_a_Transaction_with_Data.md)

View File

@ -0,0 +1,135 @@
# 8.1: Enviando uma Transação com um Locktime
Os capítulos anteriores mostraram duas maneiras diferentes de enviar fundos de várias máquinas e para vários destinatários. Mas, existem duas outras maneiras de alterar fundamentalmente as transações básicas. A primeira delas é variar o tempo, escolhendo um tempo de bloqueio ou mais conhecido pela expressão em inglês locktime. Isso nos dá a capacidade de enviar transações brutas em algum momento no futuro.
## Entendendo Como o Locktime Funciona
Ao criar uma transação do tipo locktime, a bloqueamos com um número que representa a altura do bloco (se for um número pequeno) ou um carimbo de data/hora usando o padrão UNIX (se for um número grande). Isso informa à rede Bitcoin que a transação não pode ser colocada no bloco até que o tempo especificado chegue ou a blockchain tenha atingido a altura especificada.
> :book: _O que é a altura do bloco?_ É a contagem total de blocos na blockchain, contado desde o bloco gênese até o último bloco minerado da blockchain do Bitcoin.
Quando uma transação do tipo locktime está esperando para entrar em um bloco, ela pode ser cancelada. Isso significa que ainda não foi atingido a altura ou a data necessária. Na verdade, a capacidade de cancelar é todo o propósito de uma transação do tipo locktime.
> :book: _O que é nLockTime?_ É a mesma coisa que o locktime. Mais especificamente, é como o locktime é chamado internamente no código-fonte do Bitcoin Core.
> :book: _O que é o Timelock?_ O Locktime é apenas uma maneira de bloquear transações Bitcoin até algum ponto no futuro; o coletivo desses métodos são chamados de timelocks. O locktime é o método de timelock mais básico. Ele bloqueia uma transação inteira com um tempo absoluto e está disponível através do ```bitcoin-cli``` (é por isso que é o único timelock coberto nesta seção). Um método paralelo, que bloqueia uma transação com um tempo relativo, é definido no [BIP 68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki) e abordado na seção [§11.3: Usando CSV em Scripts](11_3_Using_CSV_in_Scripts.md).
> O Bitcoin Script capacita ainda mais os dois tipos de timelocks, permitindo o bloqueio de saídas individuais ao invés de toda a transação. Os timelocks absolutos (como Locktime) estão vinculados ao opcode Script OP_CHECKLOCKTIMEVERIFY, que é definido no [BIP 65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki) e que será estudado na seção [§11.2: Usando CLTV em Scripts](11_2_Using_CLTV_in_Scripts.md), enquanto os timelocks relativos (como o Timelock) estão vinculados ao opcode de Script OP_CHECKSEQUENCEVERIFY, que é definido no [BIP 112](https://github.com/bitcoin/bips /blob/master/bip-0112.mediawiki) e que também será abordado na seção [§11.3](11_3_Using_CSV_in_Scripts.md).
## Criando uma Transação com Locktime
Para criar uma transação com locktime, precisamos primeiro determinar como definiremos o tempo.
### Descobrindo Nosso Locktime Usando o Carimbo de Data/Hora do UNIX
Provavelmente, iremos definir com muito mais frequência o nosso tempo de bloqueio usando um carimbo de data/hora do tipo UNIX que representa uma data e hora específica. Podemos calcular um carimbo de data/hora UNIX usando sites que fazem essa conversão, como o [UNIX Time Stamp](http://www.unixtimestamp.com/) ou o [Epoch Convertor](https://www.epochconverter.com/). No entanto, seria melhor [escrevermos nosso próprio script](https://www.epochconverter.com/#code) em nossa máquina local, para que saibamos que o carimbo de data/hora UNIX que recebemos está correto (lembre-se, não confie, verifique). Se não fizermos isso, pelo menos seria interessante verificar em dois sites diferentes para ter a certeza que tudo está correto.
> :book: _Por que iríamos usar um carimbo de data/hora do UNIX?_ O uso de um carimbo de data/hora do UNIX facilita a vinculação definitiva de uma transação a um horário específico, sem se preocupar se a velocidade de criação do bloco mudara drasticamente até lá. Principalmente se estivermos criando um locktime em um futuro distante, é a coisa mais segura a ser feita. Entretanto, utilizar esse método é mais intuitivo, criando uma correlação direta entre alguma data do calendário e a hora em que a transação pode ser colocada na blockchain do Bitcoin.
> :warning: **AVISO:** O Locktime com carimbos de data/hora tem menos flexibilidade, pois a liberação de blocos não é regular e os tempos de bloqueio podem ser duas horas antes do tempo real, então um locktime significa "mais ou menos nesta data e nesta hora".
### Descobrindo Nossoo Locktime Usando a Altura do Bloco
Como alternativa, podemos definir o locktime usando um número menor, que representa a altura de um bloco. Para calcular a altura do bloco futuro, precisamos primeiro saber qual é a altura do bloco atual. O ```bitcoin-cli getblockcount``` nos dirá a altura do bloco atual baseado na blockchain da máquina local. Podemos verificar um explorador do Bitcoin como a [mempool.space](https://mempool.space/).
Depois de descobrir a altura atual, podemos decidir até que ponto no futuro iremos configurar o locktime. É importante lembrar que, em média, um novo bloco será criado a cada 10 minutos. Então, por exemplo, se quisermos definir o tempo de bloqueio para uma semana no futuro, devemos escolher uma altura de bloco que é _6 x 24 x 7 = 1.008 blocos_ depois do atual.
> :book: _Por que eu usaria a altura do bloco?_ Ao contrário dos carimbos de data/hora, não existe confusão nas alturas de bloco. Se definirmos uma altura de bloco de 120.000 para o nosso locktime, não haverá absolutamente nenhuma maneira dele entrar no bloco 119.999. Isso pode tornar o controle no código mais fácil ao manipular nossa transação com locktime. A desvantagem é que não podemos ter certeza de quando exatamente será o locktime.
> :warning: **AVISO:** Se desejamos definir um locktime usando a altura do bloco, devemos definir o tempo de bloqueio para menos de 500 milhões. Se definirmos como sendo 500 milhões ou mais, nosso número será interpretado como um carimbo de data/hora. Como o carimbo de data/hora usando o padrão UNIX com valor de 500 milhões era dia 5 de novembro de 1985, provavelmente significa que nossa transação será permitida a qualquer momento a entrar na blockchain.
## Escrevendo a Transação
Depois de descobrir o locktime, tudo o que precisamos fazer é escrever uma transação bruta padrão, com uma terceira variável para o ```locktime```:
```
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.001, "'$changeaddress'": 0.00095 }''' locktime=1774650)
```
Podemos observar que o uso do ```locktime``` está abaixo dos 500 milhões, o que significa que ele define a altura do bloco. Nesse caso, são apenas alguns blocos além da altura do bloco atual no momento em que este livro foi escrito, com o objetivo de exemplificar como o locktime funciona sem ficar sentado por muito tempo para esperar para ver o que acontece.
A transação criada tem mais ou menos essa aparência:
```
$ bitcoin-cli -named decoderawtransaction hexstring=$rawtxhex
{
"txid": "ba440b1dd87a7ccb6a200f087d2265992588284eed0ae455d0672aeb918cf71e",
"hash": "ba440b1dd87a7ccb6a200f087d2265992588284eed0ae455d0672aeb918cf71e",
"version": 2,
"size": 113,
"vsize": 113,
"weight": 452,
"locktime": 1774650,
"vin": [
{
"txid": "0ad9fb6992dfe4ea90236b69852b3605c0175633b32996a486dcd0b2e739e385",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.00100000,
"n": 0,
"scriptPubKey": {
"asm": "0 f333554cc0830d03a9c1f26758e2e7e0f155539f",
"hex": "0014f333554cc0830d03a9c1f26758e2e7e0f155539f",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1q7ve42nxqsvxs82wp7fn43ch8urc425ul5um4un"
]
}
},
{
"value": 0.00095000,
"n": 1,
"scriptPubKey": {
"asm": "0 a37718a3510958112b6a766e0023ff251b6c2bfb",
"hex": "0014a37718a3510958112b6a766e0023ff251b6c2bfb",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1q5dm33g63p9vpz2m2wehqqglly5dkc2lmtmr98d"
]
}
}
]
}
```
Observe que o número de sequência (```4294967294```) é menor que ```0xffffffff```. Esta é uma sinalização necessária para mostrar que a transação inclui um locktime. Também é feito automaticamente pelo ```bitcoin-cli```. Se o número da sequência for definido como ```0xffffffff```, nosso locktime será ignorado.
> :information_source: **NOTA - SEQUÊNCIA:** Este é o segundo uso do valor ```nSequence``` em Bitcoin. Tal como acontece com o RBF, o ```nSequence``` é novamente usado como um opt-in, desta vez para o uso do locktime. O 0xffffffff-1 (4294967294) é o valor para sinalizar o tempo de bloqueio porque proíbe propositadamente o uso do RBF (que requer uma ```nSequence < 0xffffffff-1```) e do timelock relativo (que requer ```nSequence < 0xf0000000```), os outros dois usos do ```nSequence```. Se definirmos o ```nSequence``` abaixo de ```0xf0000000```, então também teremos um timelock relativo em nossa transação, o que provavelmente não é o desejado.
> :warning: **ATENÇÃO:** Se estivermos criando uma transação bruta com locktime por algum outro meio que não seja o ```bitcoin-cli```, teremos que definir a sequência para um valor menor que ```0xffffffff``` manualmente.
## Enviando a Transação
Agora, já estamos familiarizados com a parte final, que é enviar a transação para a rede:
```
$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex | jq -r '.hex')
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
error code: -26
error message:
non-final
```
Eita! Que erro é esse!?
Desde 2013, geralmente não podemos colocar a transação usando um timelock na mempool até que nosso bloqueio tenha expirado. No entanto, ainda podemos guardar nossa transação, ocasionalmente reenviando-a para a rede Bitcoin até que ela seja aceita na mempool. Uma outra opção é enviarmos a transação assinada (```$signedtx```) ao destinatário, para que ele possa colocá-la na mempool quando o tempo de bloqueio expirar.
Assim que o bloqueio de tempo expirar, qualquer pessoa pode enviar a transação assinada para a rede, e o destinatário receberá o saldo como esperado... Desde que a transação não tenha sido cancelada.
## Cancelando uma Transação com Locktime
Cancelar uma transação de tempo de bloqueio é _muito_ simples: precisamos apenas enviar uma nova transação usando pelo menos um dos UTXOs.
## Resumo: Enviando uma Transação com um Locktime
O Locktime oferece uma maneira de criar uma transação que _precisa_ esperar e que _não será aceita_ até que um determinado bloco chegue ou um momento pré-definido passe. Enquanto isso, ela pode ser cancelada simplesmente reutilizando um dos UTXO da transação.
> :fire: _Qual é o poder do locktime?_ O poder do locktime pode não ser imediatamente óbvio devido à capacidade de cancelá-lo com facilidade. No entanto, é outra das bases dos Smart Contracts, pois tem muita utilidade em uma variedade de aplicações de custódia ou contratuais. Por exemplo, considere uma situação em que um terceiro está fazendo o hold das nossas moedas. Para garantir a devolução dos nossos bitcoins caso o custodiante algum dia desaparecesse, ele poderia produzir uma transação com timelock para devolver as moedas para nós e, em seguida, atualizar isso de vez em quando com uma transação mais nova, no futuro. Se em algum momento ele não enviar a nova transação, as moedas retornarão para nós quando o timelock mais novo expirar. O timelock pode ser aplicado de forma semelhante a uma rede de pagamento, onde a rede mantém moedas enquanto estão sendo trocadas pelos participantes da rede. Finalmente, os timelocks oferecem um exemplo de contrato mais complexo, em que os pagamentos são enviados a várias pessoas. Esses pagamentos seriam baseados em transações com timelocks e seriam continuamente atualizados enquanto o proprietário continuasse a mostrar sinais de vida. (O fator unificador de todas essas aplicações é, obviamente, a _confiança_. Transações simples usando timelocks só funcionam se o detentor das moedas puder ser confiável para enviá-las sob as condições apropriadas).
## O que vem depois?
Vamos continuar "Expandindo Transações no Bitcoin" na seção [§8.2: Enviando uma Transação com Dados](08_2_Sending_a_Transaction_with_Data.md).

View File

@ -0,0 +1,121 @@
# 8.2: Enviando uma Transação com Dados
O último jeito de variar a forma como enviamos uma transação simples é usar a transação para enviar dados ao invés de saldos (ou, na prática, enviar algo além dos saldos). Isso nos dá a capacidade de inserir informações na blockchain. Isso é feito através de um comando especial, o ```OP_RETURN```.
A pegadinha? Só podemos armazenar 80 bytes por vez!
## Criando Nossos Dados
A primeira coisa que precisamos fazer é criar os 80 bytes (ou menos) de dados que iremos gravar no nosso ```OP_RETURN```. Isso pode ser tão simples quanto preparar uma mensagem ou podemos usar o hash dos dados existentes. Por exemplo, o ```sha256sum``` produz 256 bits de dados, que são apenas 32 bytes, bem abaixo do nosso limite:
```
$ sha256sum contract.jpg
b9f81a8919e5aba39aeb86145c684010e6e559b580a85003ae25d78237a12e75 contract.jpg
$ op_return_data="b9f81a8919e5aba39aeb86145c684010e6e559b580a85003ae25d78237a12e75"
```
> :book: _O que é um OP_RETURN?_ Todas as transações Bitcoin são construídas com scripts que iremos ver mais a fundo no próximo capítulo. O ```OP_RETURN``` é um script simples que define o OUTPUT como sendo inválido. A convenção resultou no uso dele para incorporar dados na blockchain.
## Separando Algumas Moedas
Nosso objetivo ao criar uma transação de dados não é enviar dinheiro para alguém, mas colocar dados dentro da blockchain. No entanto, _devemos_ gastar algumas moedas para fazer isso. Só precisamos usar um endereço de troco como sendo nosso _ único_ destinatário. Em seguida, podemos identificar um UTXO e enviá-lo para nosso endereço de troco, sem esquecer da taxa de transação, ao mesmo tempo que usamos a mesma transação para criar um OP_RETURN.
Esta é a configuração padrão:
```
$ bitcoin-cli listunspent
[
{
"txid": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
"vout": 0,
"address": "tb1q6kgsjxuqwj3rwhkenpdfcjccalk06st9z0k0kh",
"scriptPubKey": "0014d591091b8074a2375ed9985a9c4b18efecfd4165",
"amount": 0.01463400,
"confirmations": 1392,
"spendable": true,
"solvable": true,
"desc": "wpkh([d6043800/0'/1'/12']02883bb5463e37d55252d8b3d5c2141b007b37c8a7db6211f75c955acc5ea325eb)#cjr03mru",
"safe": true
}
]
$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
$ changeaddress=$(bitcoin-cli getrawchangeaddress)
```
## Escrevendo uma Transação Bruta
Agora podemos escrever uma nova transação bruta com duas saídas: uma é o nosso endereço de alteração para recuperar (a maior parte) do nosso saldo, a outra é um endereço de dados, que é uma variável ```bitcoin-cli``` para um OP_RETURN.
```
rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "data": "'$op_return_data'", "'$changeaddress'": 0.0146 }''')
```
Esta é a cara da transação:
```
{
"txid": "a600148ac3b05f0c774b8687a71c545077ea5dfb9677e5c6d708215053d892e8",
"hash": "a600148ac3b05f0c774b8687a71c545077ea5dfb9677e5c6d708215053d892e8",
"version": 2,
"size": 125,
"vsize": 125,
"weight": 500,
"locktime": 0,
"vin": [
{
"txid": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00000000,
"n": 0,
"scriptPubKey": {
"asm": "OP_RETURN b9f81a8919e5aba39aeb86145c684010e6e559b580a85003ae25d78237a12e75",
"hex": "6a20b9f81a8919e5aba39aeb86145c684010e6e559b580a85003ae25d78237a12e75",
"type": "nulldata"
}
},
{
"value": 0.01460000,
"n": 1,
"scriptPubKey": {
"asm": "0 998a9b0ed076bbdec1d88da4f475b9dde75e3620",
"hex": "0014998a9b0ed076bbdec1d88da4f475b9dde75e3620",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1qnx9fkrksw6aaaswc3kj0gademhn4ud3q7cz4fm"
]
}
}
]
}
```
Como podemos observar, ela envia a maior parte do dinheiro de volta para o endereço de troco (`tb1qnx9fkrksw6aaaswc3kj0gademhn4ud3q7cz4fm`) menos a taxa de transação. Mais importante, a primeira saída mostra um OP_RETURN com os dados (`b9f81a8919e5aba39aeb86145c684010e6e559b580a85003ae25d78237a12e75`) logo depois.
## Enviando uma Transação Bruta
Assine a transação bruta e envie-a, e logo esse OP_RETURN será incorporado a blockchain!
## Verificando Nosso OP_RETURN
Novamente, podemos olhar para essa transação usando um explorador da blockchain:
[https://mempool.space/pt/testnet/tx/a600148ac3b05f0c774b8687a71c545077ea5dfb9677e5c6d708215053d892e8/]
Podemos observar um aviso sobre os dados estarem em um "protocolo desconhecido". Se estivermos projetando algum uso regular dos dados ```OP_RETURN```, provavelmente iremos marcar com um prefixo especial, para marcar esse protocolo. Então, os dados OP_RETURN reais podem ser algo como "CONTRACTS3b110a164aa18d3a5ab064ba93fdce62". Este exemplo não usa um prefixo para evitar qualquer tipo de confusão com os espaços de dados.
## Resumo: Enviando uma Transação com Dados
Podemos usar o ```OP_RETURN``` para armazenar até 80 bytes de dados na blockchain. Fazemos isso com a palavra-código ```data``` em um ```vout```. Ainda precisaremos enviar alguns satoshinhos, mas basta enviá-lo de volta para um endereço de troco, retirando a taxa de transação.
> :fire: _Qual é o poder do OP_RETURN?_ O OP_RETURN abre novas possibilidades para o blockchain, porque podemos inserir dados que provam que certas coisas aconteceram em determinados momentos. Várias organizações estão pensando em usar os OP_RETURNs como prova de existência, para direitos autorais, para moedas coloridas e [para outros fins](https://en.bitcoin.it/wiki/OP_RETURN). Embora 80 bytes possam não parecer muito, pode ser bastante eficaz se os OP_RETURNs forem usados para armazenar hashes dos dados reais. Então, podemos provar a existência dos nossos dados digitais demonstrando que o hash deles corresponde ao hash na blockchain.
Observe que há alguma controvérsia sobre o uso da blockchain do Bitcoin usando-a para este fim.
## O Que Vem Depois?
Vamos conhecer mais sobre "Programando no Bitcoin" no [Capítulo Nove: Apresentando os Scripts do Bitcoin](09_0_Introducing_Bitcoin_Scripts.md).

View File

@ -0,0 +1,27 @@
# Capítulo 9: Apresentando os Scripts do Bitcoin
Até o momento, temos interagido com o Bitcoin em um nível relativamente alto de abstração. O programa ```bitcoin-cli``` oferece acesso a uma variedade de comandos RPC que suportam a criação e controle de transações brutas de Bitcoin que incluem saldos, dados, timelocks e multisigs.
No entanto, o Bitcoin oferece muito mais complexidade do que isso. O software oferece uma linguagem de script simples que pode ser usada para criar condições de resgate ainda mais complexas. Se os multisigs e os timelocks fornecerem as bases para os contratos inteligentes, o script do Bitcoin constrói os alicerces. É o próximo passo para capacitar o Bitcoin.
## Objetivos deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Projetar um script no Bitcoin;
* Aplicar um script no Bitcoin.
Os objetivos secundários do capítulo incluem a capacidade de:
* Compreender o propósito dos scripts no Bitcoin;
* Entender os script P2PKH;
* Entender como o P2WPKH funciona com os scripts;
* Compreender as necessidades dos testes dos scripts do bitcoin.
## Tabela de Conteúdo
* [Seção Um: Compreendendo a Base das Transações](09_1_PriveStanding_the_foundation_of_transactions.md)
* [Seção Dois: Executando um Script do Bitcoin](09_2_running_a_bitcoin_script.md)
* [Seção Três: Testando um Script do Bitcoin](09_3_testing_a_bitcoin_script.md)
* [Seção Quatro: Programando um P2PKH](09_4_scripting_a_p2pkh.md)
* [Seção Cinco: Programando um P2WPKH](09_5_scripting_a_p2wpkh.md)

View File

@ -0,0 +1,142 @@
# 9.1: Compreendendo a Base das Transações
A base do Bitcoin é a capacidade de proteger transações, algo que é feito com uma linguagem de programação simples.
## Conhecendo as Partes do Quebra-Cabeça Criptográfico
Conforme descrito no [Capítulo 1](01_0_INTRODUCING_BITCOIN.MD), os saldos em cada transação Bitcoin estão travados com um quebra-cabeça criptográfico. Para sermos mais precisos, dizemos que o Bitcoin é composto de "uma sequência de transações atômicas". Observamos que: "Cada transação é autenticada por um remetente com a solução para um quebra-cabeça criptográfico anterior que foi armazenado como um script. A nova transação é bloqueada para o destinatário com um novo quebra-cabeça criptográfico que também é armazenado como um script". Esses scripts, que bloqueiam e desbloqueiam as transações, são escritos usando o Bitcoin Script.
> :book: ***O que é o Bitcoin Script?*** O Bitcoin Script é uma linguagem baseada em pilhas (ou _stacks_), similar à linguagem de programação Forth que propositadamente evita loops, o que significa que ela não é Turing-completa. É composta de opcodes individuais. Cada transação no Bitcoin é bloqueada com um script do Bitcoin. Quando a transação de bloqueio para um UTXO é executada com as entradas corretas, esse UTXO pode então ser gasto.
O fato de que as transações estão bloqueadas com scripts significa que podem ser bloqueadas de várias maneiras diferentes, exigindo uma variedade de chaves diferentes. Na verdade, encontramos vários mecanismos de travamento diferentes até o momento, cada um dos quais usa diferentes opcodes:
* OP_CHECKSIG, que verifica uma chave pública contra uma assinatura, é a base do endereço P2PKH clássico, como será totalmente detalhado na seção [§9.4: Programando um P2PKH](09_4_Scripting_a_P2PKH.md);
* OP_CHECKMULTISIG, faz a mesma coisa com os multisigs, como será totalmente detalhado na seção [§10.4: Programando um Multisig](10_4_Scripting_a_Multisig.md);
* OP_CHECKLOCKTIMEVERIFY e OP_SEQUENCEVERIFY formam a base dos timelocks mais complexos, como será totalmente detalhado nas seções [§11.2: Usando CLTV em Scripts](11_2_Using_CLTV_in_Scripts) e [§11.3: Usando CSV em Scripts](11_3_Using_CSV_in_Scripts.md).
* OP_RETURN é a marca de uma transação não gasta, e é por isso que é usado para transportar dados, como falamos na seção [§8.2: Enviando uma Transação com Dados](08_2_sending_a_transaction_with_data.md).
## Accessando Scripts em Nossas Transações
Podemos não perceber, mas já vimos esses scripts de bloqueio e desbloqueio como parte das transações brutas que fizemos. A melhor maneira de analisar esses scripts com mais profundidade é, portanto, criar uma transação bruta e examiná-la.
### Criando uma Transação de Teste
Para examinar scripts reais de desbloqueio e bloqueio, vamos criar uma transação bruta rapidamente, pegando um UTXO legado não gasto e reenviando-o a um endereço de troco legado, deixando uma parte para as taxas de transação:
```
$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[1] | .txid')
$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[1] | .vout')
$ recipient=$(bitcoin-cli -named getrawchangeaddress address_type=legacy)
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.0009 }''')
$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex | jq -r '.hex')
```
Não precisamos enviá-la. O objetivo é simplesmente produzir uma transação para que possamos examiná-la.
>**NOTA:** Por que usar endereços legados? Porque seus scripts são mais significativos. No entanto, também ofereceremos um exemplo de um endereço nativo Segwit P2WPKH na seção [§9.5](09_5_Scripting_a_P2WPKH.md).
### Examinando Nossa Transação de Teste
Agora podemos examinar nossa transação profundamente usando ```decoderawtransaction``` no ```$signedtx```:
```
$ bitcoin-cli -named decoderawtransaction hexstring=$signedtx
{
"txid": "34151dac704d94a269cd33f80be34c122152edc9bfbb9323852966bf0ce937ed",
"hash": "34151dac704d94a269cd33f80be34c122152edc9bfbb9323852966bf0ce937ed",
"version": 2,
"size": 191,
"vsize": 191,
"weight": 764,
"locktime": 0,
"vin": [
{
"txid": "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa",
"vout": 0,
"scriptSig": {
"asm": "304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c[ALL] 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b",
"hex": "47304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c01210315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b"
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00090000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 06b5c6ba5330cdf738a2ce91152bfd0e71f9ec39 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a91406b5c6ba5330cdf738a2ce91152bfd0e71f9ec3988ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"mg8S7F1gY3ivV9M9GrWwe6ziWvK2MFquCf"
]
}
}
]
}
```
Os dois scripts são encontrados nas duas partes diferentes da transação.
O ```scriptSig``` está localizado no ```vin```. Este é o script de _desbloqueio_. É o que é executado para acessar o UTXO que está sendo usado para financiar esta transação. Haverá um ```scriptSig``` por UTXO em cada transação.
O ```scriptpubkey``` está localizado no ```vout```. Este é o script de _bloqueio_. É o que bloqueia a nova saída da transação. Haverá um ```scriptPubKey``` por cada saída em cada transação.
> :book: ***Como o scriptSig e o scriptPubKey interagem?*** O ```scriptSig``` de uma transação desbloqueia o UTXO anterior. A saída desta nova transação será bloqueada com um ```scriptPubKey```, que pode, por sua vez, ser desbloqueado pelo ```scriptSig``` da transação que reutiliza aquele UTXO.
### Lendo os Scripts na Transação
Se olharmos para os dois scripts veremos que cada um possui duas representações diferentes: o ```hex``` é o que realmente é armazenado, mas a linguagem assembly (```asm```) mais legível pode meio que mostrar o que está acontecendo.
Vamos dar uma olhada na ```asm``` do script de desbloqueio para podermos ver em primeira mão como é programar no Bitcoin:
```
04402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c[ALL] 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
```
Como acontece, essa bagunça de números é uma assinatura de chave privada, seguida pela chave pública associada. Ou pelo menos isso é o esperado, porque é isso que é necessário para desbloquear o UTXO P2PKH que esta transação está usando.
Lendo o script de bloqueio vemos que é algo muito mais óbvio:
```
OP_DUP OP_HASH160 06b5c6ba5330cdf738a2ce91152bfd0e71f9ec39 OP_EQUALVERIFY OP_CHECKSIG
```
Esse é o método padrão em Bitcoin Script para bloquear uma transação P2PKH.
A seção [§9.4](09_4_Scripting_a_P2PKH.md) explicará como esses dois scripts andam juntos, mas primeiro precisamos saber como os scripts são avaliados no Bitcoin.
## Examinando um Tipo Diferente de Transação
Antes de deixarmos esta base para trás, vamos olhar para um tipo diferente de script de bloqueio. Aqui está o ```scriptPubKey``` da transação multisig que criamos na seção [§6.1: Enviando uma Transação com Multisig](06_1_sending_a_transaction_to_a_multisig.md).
```
"scriptPubKey": {
"asm": "OP_HASH160 a5d106eb8ee51b23cf60d8bd98bc285695f233f3 OP_EQUAL",
"hex": "a914a5d106eb8ee51b23cf60d8bd98bc285695f233f387",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"2N8MytPW2ih27LctLjn6LfLFZZb1PFSsqBr"
]
}
```
Vamos comparar isso com o ```ScriptPubkey``` da nossa nova transação P2PKH:
```
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 06b5c6ba5330cdf738a2ce91152bfd0e71f9ec39 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a91406b5c6ba5330cdf738a2ce91152bfd0e71f9ec3988ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"mg8S7F1gY3ivV9M9GrWwe6ziWvK2MFquCf"
]
}
```
Essas duas transações são _definitivamente_ trancadas de maneiras diferentes. O Bitcoin reconhece a primeira como sendo ```scripthash``` (P2SH) e a segunda como sendo ```pubkeyhash``` (P2PKH), mas também devemos ser capazes de ver a diferença nos diferentes códigos ```asm```: ```OP_HASH160 a5d106eb8ee51b23cf60d8bd98bc285695f233f3 OP_EQUAL``` versus ```OP_DUP OP_HASH160 06b5c6ba5330cdf738a2ce91152bfd0e71f9ec39 Op_equalverify op_checksig```. Este é o poder da programação: conseguimos, de maneira bem simples, produzir alguns dos tipos drasticamente diferentes de transações que aprendemos nos capítulos anteriores.
## Resumo: Compreendendo a Base das Transações
Cada transação do Bitcoin inclui pelo menos um script de desbloqueio (```scriptSig```), que resolve um quebra-cabeça criptográfico anterior, e pelo menos um script de bloqueio (```scriptPubKey```), que cria um novo quebra-cabeça criptográfico. Há um ```scriptSig``` para cada entrada e um ```scriptPubKey``` para cada saída. Cada um desses scripts é escrito usando o Bitcoin Script, uma linguagem semelhante à linguagem de programação Forth que fortalece ainda mais o Bitcoin.
> :fire: ***Qual é o poder dos scripts?*** Os scripts desbloqueiam todo o poder dos contratos inteligentes. Com os opcodes apropriados, podemos tomar decisões muito precisas sobre quem pode resgatar os fundos, quando podem ser resgatados e como eles podem resgatá-los. Regras mais complexas para saldos corporativos, endereços de parceria, gastos com proxy e outras metodologias também podem ser codificados dentro de um script. Os scripts também conseguem capacitar serviços mais complexos no Bitcoin, como a Lightning e sidechains.
## O Que Vem Depois?
Vamos continuar "Apresentando os Scripts no Bitcoin" na seção [§9.2: Executando um Script no Bitcoin](09_2_Running_a_Bitcoin_Script.md).

View File

@ -0,0 +1,125 @@
# 9.2: Executando um Script do Bitcoin
Os scripts de Bitcoin podem não parecer tão intuitivos no começo, mas sua execução é bastante simples usando a notação polonesa reversa e uma pilha (_stack_).
## Compreendendo a Linguagem de Programação
Um script Bitcoin possui três partes: uma linha de entrada; uma pilha para o armazenamento; e comandos específicos para execução.
### Compreendendo a Ordem
Os scripts do Bitcoin são executados da esquerda para a direita. Para nós é fácil, porque é a mesma ordem na qual lemos. No entanto, pode na verdade ser o elemento menos intuitivo do Bitcoin Script, porque significa que as funções não têm a aparência que esperaríamos. Ao invés disso, _os operandos vêm antes do operador._
Por exemplo, se estivéssemos somando "1" e "2", nosso script do Bitcoin ficaria ```1 2 OP_ADD```, e _não_"1 + 2". Como sabemos que o operador OP_ADD recebe duas entradas, sabemos que as duas entradas anteriores são os operandos.
> :warning: **ATENÇÃO:** Tecnicamente, tudo em Bitcoin Script é um opcode, portanto, seria mais apropriado registrar o exemplo acima como ```OP_1 OP_2 OP_ADD```. Em nossos exemplos, não nos preocupamos sobre como as constantes serão avaliadas, pois esse é um tópico de tradução, como é explicado em [§10.2: Construindo a Estrutura do P2SH](10_2_Building_the_Structure_of_P2SH.md). Alguns escritores preferem também retirar o prefixo "OP" de todos os operadores, mas nós optamos por não fazê-lo.
### Compreendendo a Pilha
Na verdade, não é correto dizer que um operador se aplica às entradas anteriores. Na verdade, um operador se aplica às entradas principais na pilha do Bitcoin.
> :book: ***O que é uma pilha?*** Uma pilha é uma estrutura de dados LIFO (last in, first out, ou no português, primeiro a entrar, último a sair). Possui duas funções de acesso: push e pop. Empurrar (push) coloca um novo objeto no topo da pilha, empurrando para baixo tudo que está abaixo dele. Retirar (pop) remove o objeto superior da pilha.
Sempre que o script do Bitcoin encontrar uma constante, ele a coloca na pilha. Portanto, o exemplo acima de ```1 2 OP_ADD``` seria realmente parecido com o que foi processado:
```
Script: 1 2 OP_ADD
Stack: [ ]
Script: 2 OP_ADD
Stack: [ 1 ]
Script: OP_ADD
Stack: [ 1 2 ]
```
_Observe que, neste e nos exemplos seguintes, o topo da pilha está à direita e a parte inferior à esquerda._
### Compreendendo os Opcodes
Quando um script do Bitcoin encontra um operador, ele o avalia. Cada operador retira zero ou mais elementos da pilha como entradas, geralmente um ou dois. Em seguida, ele os processa de uma maneira específica antes de colocar zero ou mais elementos de volta na pilha, geralmente um ou dois.
> :book: ***O que é um Opcode?*** O Opcode significa "código de operação" (no inglês, "_operation code_"). É normalmente associado a código de linguagem de máquina e é uma função simples (ou "operador").
OP_ADD retira dois itens da pilha (no nosso caso: 2 depois 1), adiciona-os e coloca o resultado de volta na pilha (no exemplo: 3).
```
Script:
Running: 1 2 OP_ADD
Stack: [ 3 ]
```
## Construindo Complexidade
Scripts mais complexos são criados executando mais comandos em ordem. Eles precisam ser avaliados cuidadosamente da esquerda para a direita, para que possamos entender o estado da pilha conforme cada novo comando é executado. Ele mudará constantemente, como resultado de operadores anteriores:
```
Script: 3 2 OP_ADD 4 OP_SUB
Stack: [ ]
Script: 2 OP_ADD 4 OP_SUB
Stack: [ 3 ]
Script: OP_ADD 4 OP_SUB
Stack: [ 3 2 ]
Script: 4 OP_SUB
Running: 3 2 OP_ADD
Stack: [ 5 ]
Script: OP_SUB
Stack: [ 5 4 ]
Script:
Running: 5 4 OP_SUB
Stack: [ 1 ]
```
## Compreendendo o Uso do Bitcoin Script
É basicamente programar no Bitcoin ... além de algumas complexidades de como essa linguagem de programação interage com o próprio Bitcoin.
### Compreendendo scriptSig e scriptPubKey
Como vimos anteriormente, cada entrada de uma transação no Bitcoin contém um ```scriptSig``` que é usado para desbloquear o ```scriptPubKey``` para o UTXO associado. Eles são _efetivamente_ concatenados, o que significa que o ```scriptSig``` e o ```scriptPubKey``` são executados juntos, nessa ordem.
Então, presuma que um UTXO foi bloqueado com um ```scriptPubKey``` que leia ```OP_ADD 99 OP_EQUAL```, exigindo como entrada dois números que somam noventa e nove, e presuma que o ```scriptSig``` de ```1 98``` foi executado para desbloqueá-lo. Os dois scripts seriam efetivamente executados em ordem como ```1 98 OP_ADD 99 OP_EQUAL```.
Avaliando o resultado:
```
Script: 1 98 OP_ADD 99 OP_EQUAL
Stack: []
Script: 98 OP_ADD 99 OP_EQUAL
Stack: [ 1 ]
Script: OP_ADD 99 OP_EQUAL
Stack: [ 1 98 ]
Script: 99 OP_EQUAL
Running: 1 98 OP_ADD
Stack: [ 99 ]
Script: OP_EQUAL
Stack: [ 99 99 ]
Script:
Running: 99 99 OP_EQUAL
Stack: [ True ]
```
Esta abstração não é muito precisa: por razões de segurança, o ```scriptSig``` é executado, então o conteúdo da pilha é transferido para o ```scriptPubKey``` para ser executado, mas é precisa o suficiente para entender como a chave do ```scriptSig``` se encaixa no cadeado de ```scriptPubKey```.
> :warning: **AVISO:** O exemplo acima é um tipo de transação não-padrão. Na verdade, não seria aceito por nós que executamos o Bitcoin Core com as configurações padrões. Na seção [§10.1: Compreendendo a Base do P2SH](10_1_Understanding_the_Foundation_of_P2SH.md) iremos discutir como realmente _poderíamos_ executar um Script Bitcoin como este, usando o poder do P2SH.
### Obtendo os Resultados
O Bitcoin irá verificar uma transação e permitir que o UTXO possa ser gasto novamente se dois critérios forem atendidos ao executar o ```scriptSig``` e o ```scriptPubKey```:
1. A execução não foi marcada como inválida em nenhum ponto, por exemplo, com um OP_VERIFY com falha ou com o uso de um opcode desativado;
2. O item no topo da pilha no final da execução é verdadeiro (diferente de zero).
No exemplo acima, a transação seria bem-sucedida porque a pilha tem um ```True``` no final. Mas, seria igualmente permitido terminar com uma pilha completa e o número ```42``` no topo (os leitores do Guia do Mochileiro das Galáxias pegaram a referência).
## Resumo: Executando um Script do Bitcoin
Para processar um script no Bitcoin, um ```scriptSig``` é executado seguido pelo ```scriptPubKey``` que ele está desbloqueando. Esses comandos são executados em ordem, da esquerda para a direita, com constantes sendo colocadas em uma pilha e os operadores retirando elementos dessa pilha e, em seguida, enviando os resultados de volta para ela. Se o script não parar no meio e se o item no topo da pilha no final for diferente de zero, então o UTXO será desbloqueado.
## O Que Vem Depois?
Vamos continuar "Apresentando Scripts no Bitcoin" na seção [§9.3: Testando um Script no Bitcoin](09_3_Testing_a_Bitcoin_Script.md).

View File

@ -0,0 +1,209 @@
# 9.3: Testando um Script do Bitcoin
Programar no Bitcoin nos permite um controle adicional considerável sobre as transações no Bitcoin, mas também é um tanto quanto perigoso. Como descreveremos na seção [§10.1](10_1_Understanding_the_Foundation_of_P2SH.md), os scripts reais são um tanto isolados da rede Bitcoin, o que significa que é possível escrever um script e a rede aceitá-lo, mesmo que seja impossível resgatar daquele script! Portanto, precisamos testar exaustivamente nossos scripts antes de colocarmos nosso dinheiro neles.
Este capítulo, portanto, descreve um método primário para testar os scripts do Bitcoin, que também usaremos para os exemplos ocasionais que ocorrerem durante esta seção.
## Instalando o btcdeb
O Bitcoin Script Debugger (```btcdeb```) criado por @kallewoof é um dos métodos mais confiáveis que encontramos para depurar os scripts no Bitcoin. No entanto, ele requer a configuração de C++ e algumas coisas a mais em nossa máquina, portanto, também ofereceremos algumas outras opções no final do capítulo.
Primeiro, precisamos clonar o repositório do ```btcdeb``` do GitHub, que também exigirá a instalação do ```git``` caso ainda não o tenhamos em nossa máquina.
```
$ sudo apt-get install git
$ git clone https://github.com/bitcoin-core/btcdeb.git
```
Note que quando executamos o ```git clone```, ele irá copiar o ```btcdeb``` para o nosso diretório atual. Vamos fazer isso no diretório ```~standup```.
```
$ ls
bitcoin-0.20.0-x86_64-linux-gnu.tar.gz btcdeb laanwj-releases.asc SHA256SUMS.asc
```
Posteriormente, devemos instalar o C++ e os demais pacotes.
```
$ sudo apt-get install autoconf libtool g++ pkg-config make
```
Também precisaremos instalar o readline, pois isso torna o depurador muito mais fácil de ser usado, suportando a utilização do histórico usando as setas para cima e para baixo, movimento da esquerda para a direita, além do preenchimento automático usando tab e outras interfaces boas para o usuário.
```
$ sudo apt-get install libreadline-dev
```
Agora estamos prontos para compilar e instalar o ```btcdeb```:
```
$ cd btcdeb
$ ./autogen.sh
$ ./configure
$ make
$ sudo make install
```
Depois de tudo isso, devemos ter uma cópia do ```btcdeb``` em nossa máquina:
```
$ which btcdeb
/usr/local/bin/btcdeb
```
## Usando o btcdeb
O ```btcdeb``` funciona como um depurador padrão. Ele pega um script (bem como qualquer número de entradas da pilha) como um argumento de inicialização. Em seguida, podemos percorrer o script usando o ```step```.
Se ao invés disso nós quisermos inicializá-lo sem argumentos, iremos obter simplesmente um interpretador onde podemos emitir comandos ```exec [opcode]``` para realizar ações diretas.
### Usando o btcdeb com um Exemplo de Adição
O exemplo a seguir mostra o uso do ```btcdeb``` usando como exemplo a adição da seção anterior, ```1 2 OP_ADD```
```
$ btcdeb '[1 2 OP_ADD]'
btcdeb 0.2.19 -- type `btcdeb -h` for start up options
warning: ambiguous input 1 is interpreted as a numeric value; use OP_1 to force into opcode
warning: ambiguous input 2 is interpreted as a numeric value; use OP_2 to force into opcode
miniscript failed to parse script; miniscript support disabled
valid script
3 op script loaded. type `help` for usage information
script | stack
--------+--------
1 |
2 |
OP_ADD |
#0000 1
```
Ele mostra nosso script inicial, rodando de cima para baixo, e também mostra o que será executado a seguir no script.
Nós precisamos digitar ```step``` para ele avançar um passo pegando o primeiro item no script e colocando-o na pilha:
```
btcdeb> step
<> PUSH stack 01
script | stack
--------+--------
2 | 01
OP_ADD |
#0001 2
```
E novamente:
```
btcdeb> step
<> PUSH stack 02
script | stack
--------+--------
OP_ADD | 02
| 01
#0002 OP_ADD
```
Agora executamos o ```OP_ADD``` e há uma grande empolgação porque esse opcode tira os primeiros dois itens da pilha, faz a soma e, em seguida, coloca o resultado na pilha.
```
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 03
script | stack
--------+--------
| 03
```
E é aí que nosso script termina, sem mais nada para executar e com um ```03``` no topo da pilha como resultado do script.
> **NOTA:** O ```btcdeb``` nos permite repetir o comando anterior pressionando apenas a tecla enter. Faremos isso em exemplos subsequentes, então não fique assustado com os prompts ```btcdeb>``` se não houver nenhum comando. Isto está apenas repetindo o comando anterior (geralmente o ```step```).
### Usando o btcdeb com um Exemplo de Subtração
A seção anterior também incluiu um exemplo de subtração um pouco mais complexo na criação do script: ```3 2 OP_ADD 4 OP_SUB```. Isso é o resultado:
```
$ btcdeb '[3 2 OP_ADD 4 OP_SUB]'
btcdeb 0.2.19 -- type `btcdeb -h` for start up options
warning: ambiguous input 3 is interpreted as a numeric value; use OP_3 to force into opcode
warning: ambiguous input 2 is interpreted as a numeric value; use OP_2 to force into opcode
warning: ambiguous input 4 is interpreted as a numeric value; use OP_4 to force into opcode
miniscript failed to parse script; miniscript support disabled
valid script
5 op script loaded. type `help` for usage information
script | stack
--------+--------
3 |
2 |
OP_ADD |
4 |
OP_SUB |
#0000 3
btcdeb> step
<> PUSH stack 03
script | stack
--------+--------
2 | 03
OP_ADD |
4 |
OP_SUB |
#0001 2
btcdeb>
<> PUSH stack 02
script | stack
--------+--------
OP_ADD | 02
4 | 03
OP_SUB |
#0002 OP_ADD
btcdeb>
<> POP stack
<> POP stack
<> PUSH stack 05
script | stack
--------+--------
4 | 05
OP_SUB |
#0003 4
btcdeb>
<> PUSH stack 04
script | stack
--------+--------
OP_SUB | 04
| 05
#0004 OP_SUB
btcdeb>
<> POP stack
<> POP stack
<> PUSH stack 01
script | stack
--------+--------
| 01
```
Voltaremos ao ```btcdeb``` de tempos em tempos, e ele continuará sendo uma excelente ferramenta para testarmos nossos scripts.
### Usando o Poder do btcdeb
O ```btcdeb``` também tem algumas funções mais poderosas, como ```print``` e ```stack```, que mostram o script e a pilha a qualquer momento da execução.
Por exemplo, no script acima, depois de avançar para o comando ```OP_ADD```, podemos fazer o seguinte:
```
btcdeb> print
#0000 3
#0001 2
-> #0002 OP_ADD
#0003 4
#0004 OP_SUB
btcdeb> stack
<01> 02 (top)
<02> 03
```
Usar esses comandos pode tornar mais fácil observarmos o que está acontecendo e onde estamos no processo.
## Testando um Script Online
Existem também alguns simuladores na web que podemos usar para testar os scripts online. Eles podem ser superiores a uma ferramenta de linha de comando, oferecendo uma saída gráfica melhor, mas também descobrimos que eles tendem a ter certas deficiências.
No passado, tentamos fornecer diretrizes abrangentes sobre o uso de sites como o [Script Playground](http://www.crmarsh.com/script-playground/) ou o [Bitcoin Online Script Debugger](https: // bitcoin-script-debugger.visvirial.com/), mas eles estão desatualizados e/ou sumiram e não podemos mais acompanhá-los.
O que podemos garantir é que esses depuradores possuem a vantagem de mostrar coisas visualmente e explicitamente informando se um script foi bem-sucedido (desbloqueado) ou que houve falha (permanece bloqueado). Porém eles possuem algumas desvantagens relacionadas as assinaturas, onde muitos deles sempre retornam ```true``` para testes de assinatura ou então possuem mecanismos muito complicados para incorporá-las.
## Testando um Script com Bitcoin
Mesmo com uma ótima ferramenta como o ```btcdeb``` ou recursos transitórios como os diversos testadores de script online, não estamos trabalhando com a coisa real. Não podemos garantir que elas seguem as regras de consenso do Bitcoin, o que significa que não podemos garantir os resultados. Por exemplo, o Script Playground diz explicitamente que ignora um bug que está implícito quando usando o multisig no Bitcoin. Isso significa que qualquer código multisig que testarmos com sucesso no Script Playground dará erro no mundo real.
Portanto, a única maneira de _realmente_ testar os scripts do Bitcoin é testá-los usando a Testnet.
E como podemos faz isso? Acontece que esse é o tópico do [capítulo 10](10_0_Embedding_Bitcoin_Scripts_in_P2SH_Transactions.md), que examina a introdução desses scripts abstratos no mundo real do Bitcoin incorporando-os em transações P2SH. (Mas, mesmo assim, provavelmente precisaremos de uma API para enviar nossa transação P2SH para a rede Bitcoin, então os testes completos ainda serão produzidos no futuro).
_Quaisquer que sejam_ os outros métodos de teste que usamos, testar um script na Testnet deve ser nosso teste final _antes_ de colocar nosso script em Mainnet. Não podemos confiar que nosso código está correto. Não podemos fazer isso apenas olhando para ele. Nem mesmo podemos confiar em quaisquer simuladores ou depuradores que estivermos utilizando. Fazer isso é outra ótima maneira de perder seu saldo no Bitcoin.
## Resumo: Testando um Script do Bitcoin
Você deve instalar o ```btcdeb``` como uma ferramenta de linha de comando para testar os scripts do Bitcoin. No momento em que este livro foi escrito, produzimos resultados precisos que podem percorrer todo o processo do script. Também podemos procurar em alguns sites online uma representação mais visual. Quando estivermos com tudo pronto, vamos precisar usar a testnet para ter certeza de que as coisas estão funcionando com precisão, antes de implantarmos na Mainnet.
## O Que Vem Depois?
Vamos continuar "Apresentando Scripts no Bitcoin" com nosso primeiro exemplo real na seção [§9.4: Programando um P2PKH](09_4_Scripting_a_P2PKH.md).

View File

@ -0,0 +1,389 @@
# 9.4: Programando um P2PKH
Os endereços P2PKH estão desaparecendo rapidamente devido ao advento do Segwit, porém, são importantes para entender o Bitcoin, e especialmente para entender os scripts do Bitcoin. Vamos dar uma olhada rápida como os scripts nativos do Segwit (P2WPKH) funcionam na próxima seção.
## Entendendo o Script de Desbloqueio
Dissemos que quando os fundos são enviados para um endereço de bitcoin, eles estão bloqueados juntamente com a chave privada associada a esse endereço. Isso é gerenciado através do ```scriptPubKey``` de uma transação P2PKH, que é projetado de forma que requer que o destinatário tenha a chave privada associada ao endereço bitcoin do tipo P2PKH. Para ser preciso, o destinatário deve fornecer tanto a chave pública ligada à chave privada quanto uma assinatura gerada pela chave privada.
Vamos dar uma olhada novamente na transação que criamos na seção [§9.1](09_1_Understanding_the_Foundation_of_Transactions.md):
```
$ bitcoin-cli -named decoderawtransaction hexstring=$signedtx
{
"txid": "34151dac704d94a269cd33f80be34c122152edc9bfbb9323852966bf0ce937ed",
"hash": "34151dac704d94a269cd33f80be34c122152edc9bfbb9323852966bf0ce937ed",
"version": 2,
"size": 191,
"vsize": 191,
"weight": 764,
"locktime": 0,
"vin": [
{
"txid": "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa",
"vout": 0,
"scriptSig": {
"asm": "304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c[ALL] 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b",
"hex": "47304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c01210315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b"
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00090000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 06b5c6ba5330cdf738a2ce91152bfd0e71f9ec39 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a91406b5c6ba5330cdf738a2ce91152bfd0e71f9ec3988ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"mg8S7F1gY3ivV9M9GrWwe6ziWvK2MFquCf"
]
}
}
]
}
```
Podemos ver que o script de desbloqueio do ```scriptSig``` tem dois valores, uma ```<signature>``` (e um ```[ALL]```) e uma ```<pubkey>```:
```
304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c[ALL] 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
```
Isso é tudo que um script de desbloqueio é! (No caso de um endereço P2PKH).
## Entendendo o Script de Bloqueio
Lembre-se de que cada script de desbloqueio desbloqueia um UTXO anterior. No exemplo acima, o ```vin``` revela que é realmente desbloqueado o vout ```0``` da txid ```bb4362dec15e67d366088f5493c789f22fbb4a6049f22fb4a604e767dae1f6a631687E2784aa```.
Podemos examinar esse UTXO usando o comando ```gettransaction```.
```
$ bitcoin-cli gettransaction "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa"
{
"amount": 0.00095000,
"confirmations": 12,
"blockhash": "0000000075a4c1519da5e671b15064734c42784eab723530a6ace83ca1e66d3f",
"blockheight": 1780789,
"blockindex": 132,
"blocktime": 1594841768,
"txid": "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa",
"walletconflicts": [
],
"time": 1594841108,
"timereceived": 1594841108,
"bip125-replaceable": "no",
"details": [
{
"address": "mmX7GUoXq2wVcbnrnFJrGKsGR14fXiGbD9",
"category": "receive",
"amount": 0.00095000,
"label": "",
"vout": 0
}
],
"hex": "020000000001011efcc3bf9950ac2ea08c53b43a0f8cc21e4b5564e205f996f7cadb7d13bb79470000000017160014c4ea10874ae77d957e170bd43f2ee828a8e3bc71feffffff0218730100000000001976a91441d83eaffbf80f82dee4c152de59a38ffd0b602188ac713b10000000000017a914b780fc2e945bea71b9ee2d8d2901f00914a25fbd8702473044022025ee4fd38e6865125f7c315406c0b3a8139d482e3be333727d38868baa656d3d02204b35d9b5812cb85894541da611d5cec14c374ae7a7b8ba14bb44495747b571530121033cae26cb3fa063c95e2c55a94bd04ab9cf173104555efe448b1bfc3a68c8f873342c1b00"
}
```
Mas como podemos observar, não recebemos o ```scriptPubKey``` com o ```gettransaction```. Precisamos dar um passo adicional para recuperar essa informação, examinando as informações da transação bruta (que é o ```hex```) com o ```Decoderawtransaction```:
```bash
$ hex=$(bitcoin-cli gettransaction "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa" | jq -r '.hex')
$ bitcoin-cli decoderawtransaction $hex
{
"txid": "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa",
"hash": "6866490b16a92d68179e1cf04380fd08f16ec80bf66469af8d5e78ae624ff202",
"version": 2,
"size": 249,
"vsize": 168,
"weight": 669,
"locktime": 1780788,
"vin": [
{
"txid": "4779bb137ddbcaf796f905e264554b1ec28c0f3ab4538ca02eac5099bfc3fc1e",
"vout": 0,
"scriptSig": {
"asm": "0014c4ea10874ae77d957e170bd43f2ee828a8e3bc71",
"hex": "160014c4ea10874ae77d957e170bd43f2ee828a8e3bc71"
},
"txinwitness": [
"3044022025ee4fd38e6865125f7c315406c0b3a8139d482e3be333727d38868baa656d3d02204b35d9b5812cb85894541da611d5cec14c374ae7a7b8ba14bb44495747b5715301",
"033cae26cb3fa063c95e2c55a94bd04ab9cf173104555efe448b1bfc3a68c8f873"
],
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.00095000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 41d83eaffbf80f82dee4c152de59a38ffd0b6021 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a91441d83eaffbf80f82dee4c152de59a38ffd0b602188ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"mmX7GUoXq2wVcbnrnFJrGKsGR14fXiGbD9"
]
}
},
{
"value": 0.01063793,
"n": 1,
"scriptPubKey": {
"asm": "OP_HASH160 b780fc2e945bea71b9ee2d8d2901f00914a25fbd OP_EQUAL",
"hex": "a914b780fc2e945bea71b9ee2d8d2901f00914a25fbd87",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"2N9yWARt5E3TQsX2RjsauxSZaEZVhinAS4h"
]
}
}
]
}
```
Podemos olhar agora para o ```vout``` ```0``` e ver que ele foi bloqueado com o ```scriptPubKey``` no ```OP_DUP OP_HASH160 41d83eaffbf80f82dee4c152de59a38ffd0b6021 OP_EQUALVERIFY OP_CHECKSIG```. Essa é a metodologia de bloqueio padrão usada para um endereço P2PKH mais antigo com o `<pubKeyHash>` preso no meio.
Executando-o demonstrará seu funcionamento.
## Executando um Script P2PKH
Quando desbloqueamos um UTXO do tipo P2PKH, efetivamente concatenamos os scripts de desbloqueio e de bloqueio. Para um endereço P2PKH, como o exemplo que usamos neste capítulo, isso produz o seguinte:
```
Script: <signature> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
```
Com essas informações juntas, podemos examinar como um UTXO P2PKH é desbloqueado.
Primeiro, colocamos as constantes iniciais na pilha, depois fazemos uma cópia do pubKey com o `OP_DUP`:
```
Script: <signature> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Stack: [ ]
Script: <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Stack: [ <signature> ]
Script: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Stack: [ <signature> <pubKey> ]
Script: OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Running: <pubKey> OP_DUP
Stack: [ <signature> <pubKey> <pubKey> ]
```
Por que duplicar? Porque é necessário verificar os dois elementos de desbloqueio, a chave pública e a assinatura.
Em seguida, o ```OP_HASH160``` retira o ```<pubKey>``` fora da pilha, cria um hash e coloca o resultado de volta nela.
```
Script: <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Running: <pubKey> OP_HASH160
Stack: [ <signature> <pubKey> <pubKeyHash> ]
```
Então, colocamos o ```<pubKeyHash>``` que estava no script de bloqueio na pilha:
```
Script: OP_EQUALVERIFY OP_CHECKSIG
Stack: [ <signature> <pubKey> <pubKeyHash> <pubKeyHash> ]
```
O ```OP_EQUALVERIFY``` é efetivamente dois opcodes: ```OP_EQUAL```, que retira dois itens da pilha e coloca `True` ou `False` de volta baseado na comparação de ambos elementos; e o ```OP_VERIFY``` que retira o resultado e imediatamente marca a transação como inválida se for ```False```. (No capítulo 12 falaremos mais sobre o uso de ```OP_VERIFY``` como condicional.)
Assumindo que os dois ```<pubKeyHash>``` são iguais, teremos o seguinte resultado:
```
Script: OP_CHECKSIG
Running: <pubKeyHash> <pubKeyHash> OP_EQUALVERIFY
Stack: [ <signature> <pubKey> ]
```
Neste momento, provamos que a `<pubkey>` fornecida no `scriptSig` leva ao endereço Bitcoin em questão, então sabemos que o redentor conhecia a chave púbica. Mas, ele também precisa provar o conhecimento da chave privada, o que é feito com os ```OP_CHECKSIG```, que confirmam que a assinatura do script de desbloqueio corresponde a essa chave pública.
```
Script:
Running: <signature> <pubKey> OP_CHECKSIG
Stack: [ True ]
```
O script agora termina e, se foi bem sucedido, a transação é permitida para gastar o UTXO em questão novamente.
### Usando o btcdeb em um Exemplo P2PKH
Testando transações de bitcoin reais com o ```btcdeb``` é um pouco mais complicado, porque precisamos conhecer a chave pública e uma assinatura para fazer todo o trabalho, e gerar o último é um pouco difícil. No entanto, uma maneira de testar as coisas é deixar o Bitcoin fazer o trabalho para nós, gerando uma transação que _possa_ desbloquear um UTXO. Isso é o que fizemos acima, geramos a transação para gastar o UTXO criado pelo ```bitcoin-cli``` para calcular a ```<signature>``` e a ```<pubKey>```. Podemos analisar as informações da transação bruta do UTXO para conhecer o script de bloqueio, incluindo o ```<pubKeyHash>```.
Podemos montar o script de bloqueio, a assinatura e a pubkey usando o `btcdeb`, mostrando como pode ser simples um script P2PKH .
```
$ btcdeb '[304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b OP_DUP OP_HASH160 41d83eaffbf80f82dee4c152de59a38ffd0b6021 OP_EQUALVERIFY OP_CHECKSIG]'
btcdeb 0.2.19 -- type `btcdeb -h` for start up options
unknown key ID 41d83eaffbf80f82dee4c152de59a38ffd0b6021: returning fake key
valid script
7 op script loaded. type `help` for usage information
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b... |
0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b |
OP_DUP |
OP_HASH160 |
41d83eaffbf80f82dee4c152de59a38ffd0b6021 |
OP_EQUALVERIFY |
OP_CHECKSIG |
|
|
#0000 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c
```
Colocamos a ```<signature>``` e a ```<pubKey>``` dentro da pilha:
```
btcdeb> step
<> PUSH stack 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b...
OP_DUP |
OP_HASH160 |
41d83eaffbf80f82dee4c152de59a38ffd0b6021 |
OP_EQUALVERIFY |
OP_CHECKSIG |
|
|
|
|
|
#0001 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
btcdeb> step
<> PUSH stack 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
OP_DUP | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
OP_HASH160 | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b...
41d83eaffbf80f82dee4c152de59a38ffd0b6021 |
OP_EQUALVERIFY |
OP_CHECKSIG |
|
|
|
|
|
|
|
```
Usamos o ```OP_DUP``` e o ```OP_HASH``` na ```<pubKey>```:
```
#0002 OP_DUP
btcdeb> step
<> PUSH stack 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
OP_HASH160 | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
41d83eaffbf80f82dee4c152de59a38ffd0b6021 | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
OP_EQUALVERIFY | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b...
OP_CHECKSIG |
|
|
|
|
|
|
|
|
|
#0003 OP_HASH160
btcdeb> step
<> POP stack
<> PUSH stack 41d83eaffbf80f82dee4c152de59a38ffd0b6021
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
41d83eaffbf80f82dee4c152de59a38ffd0b6021 | 41d83eaffbf80f82dee4c152de59a38ffd0b6021
OP_EQUALVERIFY | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
OP_CHECKSIG | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b...
|
|
|
|
|
|
|
|
|
|
```
Depois colocamos o ```<pubKeyHash>``` do script de bloqueio na pilha e o verificamos:
```
#0004 41d83eaffbf80f82dee4c152de59a38ffd0b6021
btcdeb> step
<> PUSH stack 41d83eaffbf80f82dee4c152de59a38ffd0b6021
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
OP_EQUALVERIFY | 41d83eaffbf80f82dee4c152de59a38ffd0b6021
OP_CHECKSIG | 41d83eaffbf80f82dee4c152de59a38ffd0b6021
| 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
| 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b...
|
|
|
|
|
|
|
|
|
|
#0005 OP_EQUALVERIFY
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 01
<> POP stack
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
OP_CHECKSIG | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
| 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b...
|
| and_v(
| sig(304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c...
| and_v(
| pk(0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3...
| c:pk_h(030500000000000000000000000000000000000000000000...
| )
|
| )
|
```
E nesse ponto, tudo o que é necessário é o ```OP_CHECKSIG```:
```
#0006 OP_CHECKSIG
btcdeb> step
error: Signature is found in scriptCode
```
Infelizmente, esta verificação pode ou não estar funcionando no momento do teste devido a caprichos do Bitcoin Core e do `btcdeb`.
Como mostramos, um P2PKH é bastante simples. Nossa proteção vem através da força de sua criptografia.
### Como Procurar uma PubKey e uma Assinatura Manualmente
E se quiséssemos gerar a ```<signature>``` e a ```<PubKey>```, informações necessárias para desbloquear um UTXO, sem usar o ```bitcoin-cli``` para criar uma transação?
Acontece que é muito fácil obtermos uma ````<pubKey>````. Nós precisamos usar o ```getaddressinfo``` para examinar o endereço onde o UTXO está:
```
$ bitcoin-cli getaddressinfo mmX7GUoXq2wVcbnrnFJrGKsGR14fXiGbD9
{
"address": "mmX7GUoXq2wVcbnrnFJrGKsGR14fXiGbD9",
"scriptPubKey": "76a91441d83eaffbf80f82dee4c152de59a38ffd0b602188ac",
"ismine": true,
"solvable": true,
"desc": "pkh([f004311c/0'/0'/2']0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b)#t3g5mjk9",
"iswatchonly": false,
"isscript": false,
"iswitness": false,
"pubkey": "0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b",
"iscompressed": true,
"ischange": false,
"timestamp": 1594835792,
"hdkeypath": "m/0'/0'/2'",
"hdseedid": "f058372260f71fea37f7ecab9e4c5dc25dc11eac",
"hdmasterfingerprint": "f004311c",
"labels": [
""
]
}
```
Descobrir essa assinatura, no entanto, requer que entendamos os meandros de como as transações do Bitcoin são criadas. Portanto, vamos deixar isso como sendo um estudo avançado para você leitor: criando uma transação de ```bitcoin-cli``` para "resolver" o UTXO é a melhor solução para isso neste momento.
## Resumo: Programando um P2PKH
Enviar para um endereço P2PKH foi relativamente fácil quando estávamos usando o ````bitcoin-cli````. Examinando o script do Bitcoin subjacente nos revela as funções criptográficas que estavam implícitas no financiamento da transação: como o UTXO foi desbloqueado com uma assinatura e uma chave pública.
## O Que Vem Depois?
Vamos continuar "Apresentando Scripts no Bitcoin" na seção [§9.5: Programando um P2WPKH](09_5_Scripting_a_P2WPKH.md).

View File

@ -0,0 +1,119 @@
# 9.5: Programando um P2WPKH
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão. Cautela, leitor.
Os P2PKHs são bons para explicar a maneira fundamental de como os scripts de Bitcoin funcionam, mas por que os scripts SegWit P2WPKH nativos estão se tornando cada vez mais a maioria das transações no Bitcoin? Acontece que os endereços P2WPKH não usam Scripts de Bitcoin como os endereços de Bitcoin tradicionais fazem e, portanto, esta seção é realmente uma digressão do script deste capítulo, mas ela é importante, porque descreve a _outra_ maneira principal pela qual bitcoins podem ser transacionados.
## Observando um Script P2WPKH
É fácil ver a aparência de um script P2WPKH. A transação bruta abaixo foi criada gastando um UTXO P2WPKH e, em seguida, enviando o dinheiro para um endereço de troco P2WPKH, assim como fizemos com um endereço legado na seção [§9.1](09_1_Understanding_the_Foundation_of_Transactions.md).
```
$ bitcoin-cli -named decoderawtransaction hexstring=$signedtx
{
"txid": "bdf8f12768a9870d41ac280f8bb4f8ecd9d2fa66fffc75606811f5751c17cb3a",
"hash": "ec09c84cae48694bec7fd3461b3c5b38a76829c56e9d876037bf2484d443174b",
"version": 2,
"size": 191,
"vsize": 110,
"weight": 437,
"locktime": 0,
"vin": [
{
"txid": "3f5417bc7a3a4144d715f3f006d35ea2b405f06091cbb9ce492e04ccefe02b18",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"txinwitness": [
"3044022064f633ccfc4e937ef9e3edcaa9835ea9a98d31fbea1622c1d8a38d4e7f8f6cb602204bffef45a094de1306f99da055bd5a603a15c277a59a48f40a615aa4f7e5038001",
"03839e6035b33e37597908c83a2f992ec835b093d65790f43218cb49ffe5538903"
],
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00090000,
"n": 0,
"scriptPubKey": {
"asm": "0 92a0db923b3a13eb576a40c4b35515aa30206cba",
"hex": "001492a0db923b3a13eb576a40c4b35515aa30206cba",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1qj2sdhy3m8gf7k4m2grztx4g44gczqm96y6sszv"
]
}
}
]
}
```
Provavelmente existem duas coisas surpreendentes aqui: (1) Não há ```scriptSig``` para desbloquear a transação anterior e; (2) o ```scriptPubKey``` para bloquear a nova transação é apenas ```0 92a0db923b3a13eb576a40c4b35515aa30206cb```.
Isso é assim porque o P2WPKH funciona de forma diferente!
## Compreendendo uma Transação P2WPKH
Uma transação P2WPKH contém todas as mesmas informações que uma transação P2PKH clássica, mas a coloca em lugares diferentes, não dentro de um script Bitcoin tradicional, e essa é a cereja do bolo das transações SegWit, pois retira as informações "witness" (testemunhas), que são as chaves públicas e as assinaturas, para fora da transação, dando suporte a uma mudança de tamanho do bloco.
Mas, se olharmos com cuidado, veremos que o ```scriptSig``` vazio foi substituído por duas entradas em uma nova seção chamada ```txinwitness```. Se examinarmos os tamanhos e formatações, eles devem parecer familiares, afinal, elas são uma assinatura e uma chave pública. Da mesma forma, se olharmos o `scriptPubKey`, veremos que é feito de um ```0``` (na verdade, de um ```OP_0```, que é o número da versão do SegWit) e outro número longo, que é o hash de chave pública.
Aqui está uma comparação dos nossos dois exemplos:
| Tipo | PubKeyHash | PubKey | Signature |
|----------------|----------|-------------|---------|
| SegWit | 92a0db923b3a13eb576a40c4b35515aa30206cba | 03839e6035b33e37597908c83a2f992ec835b093d65790f43218cb49ffe5538903 | 3044022064f633ccfc4e937ef9e3edcaa9835ea9a98d31fbea1622c1d8a38d4e7f8f6cb602204bffef45a094de1306f99da055bd5a603a15c277a59a48f40a615aa4f7e5038001 |
| SegWit | 06b5c6ba5330cdf738a2ce91152bfd0e71f9ec39 | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b | 04402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c |
Então, como isso tudo funciona? Depende da interpretação do código antigo como uma transação válida e do conhecimento do novo código para verificar as novas informações "testemunhas".
### Lendo um Script SegWit em uma Máquina Antiga
Se um node não foi atualizado para suportar SegWit, então ele faz o seu truque usual de concatenar o ```scriptSig``` e o ```scriptPubKey```. Isso produz o seguinte: ```0 92a0db923b3a13eb576a40c4b35515aa30206cba``` (porque há apenas um ```scriptPubKey```). Ao executar isso, iremos produzir uma pilha com tudo na ordem inversa:
```
$ btcdeb '[0 92a0db923b3a13eb576a40c4b35515aa30206cba]'
btcdeb 0.2.19 -- type `btcdeb -h` for start up options
miniscript failed to parse script; miniscript support disabled
valid script
2 op script loaded. type `help` for usage information
script | stack
-----------------------------------------+--------
0 |
92a0db923b3a13eb576a40c4b35515aa30206cba |
#0000 0
btcdeb> step
<> PUSH stack
script | stack
-----------------------------------------+--------
92a0db923b3a13eb576a40c4b35515aa30206cba | 0x
#0001 92a0db923b3a13eb576a40c4b35515aa30206cba
btcdeb> step
<> PUSH stack 92a0db923b3a13eb576a40c4b35515aa30206cba
script | stack
-----------------------------------------+-----------------------------------------
| 92a0db923b3a13eb576a40c4b35515aa30206cba
| 0x
```
Os scripts do Bitcoin são considerados bem-sucedidos se houver algo na pilha e ele for diferente de zero, portanto, os scripts SegWit são automaticamente bem-sucedidos nos nodes antigos, desde que o ```scriptPubKey``` seja criado corretamente com um hash de uma pub-key diferente de zero. Isso é chamado de transação _"anyone-can-spend"_, ou no português, _"qualquer-um-pode-gastar"_, porque os nodes antigos os verificaram como corretos sem a necessidade de assinaturas.
> :book: ***Os nodes antigos não podem roubar os UTXOs do SegWit?*** O SegWit foi habilitado na rede Bitcoin quando 95% dos mineradores sinalizaram que estavam prontos para começar a utilizá-lo. Isso significa que apenas 5% dos nodes naquele momento podem ter registrado transações SegWit que _qualquer-um-pode-gastar_ como sendo válidas, sem passar pelo trabalho adequado de verificação dos ```txinwitness```. Se incorporassem incorretamente um UTXO inválido que _qualquer-um-pode-gastar_ em um bloco, os outros 95% dos nodes se recusariam a validar esse bloco, e assim ele ficaria rapidamente órfão ao invés de ser adicionado à blockchain "principal". (Certamente, 51% dos nodes poderiam escolher parar de interpretar as transações SegWit corretamente, mas 51% dos nodes podem fazer qualquer coisa em uma rede de consenso, como uma blockchain).
Como os nodes antigos sempre acham que os scripts SegWit estão corretos, eles sempre os verificam, mesmo sem entender seu conteúdo.
### Lendo um Script SegWit em uma Máquina Nova
Uma máquina que entende como o SegWit funciona faz exatamente as mesmas coisas que faria com um script P2PKH antigo, mas não usa o script por si só. Ela apenas sabe que precisa fazer o hash da chave pública no ```txinwitness```, verificando-a usando a chave hash após o número da versão no ```scriptPubKey``` e, em seguida, executando o ```OP_CHECKSIG``` na assinatura e na chave pública do ```txinwitness```.
Portanto, é outra maneira de fazer a mesma coisa, mas sem ter os scripts embutidos nas transações. Ao invés disso, o processo é integrado ao software do node.
## Resumo: Programando um P2WPKH
Em grande parte, _não_ programamos um P2WPKH. Ao invés disso, o Bitcoin Core cria a transação de uma maneira diferente, colocando as informações da testemunha em um lugar diferente ao invés de um ```scriptSig``` tradicional. Isso significa que os P2WPKHs são uma digressão dos scripts de Bitcoin desta parte do livro, porque são uma expansão do Bitcoin que se distancia dos scripts tradicionais.
No entanto, o SegWit também usa os scripts do Bitcoin de maneira inteligente. Sabendo que haveria nodes que não seriam atualizados e que precisariam permanecer compatíveis com versões anteriores, os desenvolvedores criaram o formato P2WPKH de forma que gerasse um script que sempre seria validado nos nodes antigos (embora ainda tivesse aquele script fornecendo informações para os nodes novos em uma forma de um número de versão e uma chave pública com hash).
Quando estamos programando usando a linha de comando, fundamentalmente não precisamos nos preocupar com isso, a não ser com saber que não encontraremos os scripts tradicionais em transações brutas do tipo SegWit (o que, novamente, era o ponto desta seção).
## O Que Vem Depois?
Vamos continuar "Programando no Bitcoin" no [Capítulo 10: Incorporando Scripts em Transações P2SH no Bitcoin](10_0_Embedding_Bitcoin_Scripts_in_P2SH_Transactions.md).

View File

@ -0,0 +1,26 @@
# Capítulo 10: Incorporando Scripts em Transações P2SH no Bitcoin
O Bitcoin Script desce vários níveis de abstração, permitindo que controlemos minuciosamente as condições de resgate dos fundos. Mas, como realmente incorporamos esses scripts do Bitcoin nas transações que construímos até agora? A resposta é um novo tipo de transação de Bitcoin, o P2SH.
## Objetivos deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Projetar uma transação P2SH;
* Aplicar um script P2SH Bitcoin.
Os objetivos secundários do capítulo incluem a capacidade de:
* Compreender o script P2SH;
* Compreender o script Multisig;
* Compreender as várias variações dos scripts Segwit;
* Entender como gastar fundos enviados a um P2SH.
## Tabela de Conteúdo
* [Seção 1: Compreendendo a Base do P2SH](10_1_Understanding_the_Foundation_of_P2SH.md)
* [Seção 2: Construindo a Estrutura do P2SH](10_2_Building_the_Structure_of_P2SH.md)
* [Seção 3: Executando um Script do Bitcoin com P2SH](10_3_Running_a_Bitcoin_Script_with_P2SH.md)
* [Seção 4: Programando um Multisig](10_4_Scripting_a_Multisig.md)
* [Seção 5: Programando um Script Segwit](10_5_Scripting_a_Segwit_Script.md)
* [Seção 6: Gastando uma Transação P2SH](10_6_Spending_a_P2SH_Transaction.md)

View File

@ -0,0 +1,100 @@
# 10.1: Compreendendo a Base do P2SH
Sabemos que os scripts do Bitcoin podem ser usados para controlar o resgate dos UTXOs. A próxima etapa é criar os nossos próprios scripts... mas isso requer uma técnica muito específica.
## Conhecendo os Padrões do Bitcoin
Aqui está a pegadinha sobre como usar scripts do Bitcoin: Por razões de segurança, a maioria dos nodes do Bitcoin aceitará apenas seis tipos de transações de Bitcoin, ditas como "padrão".
* __Pay to Public Key (P2PK)__ - O tipo de transação mais antiga e obsoleta (```<pubKey> OP_CHECKSIG```) que foi substituída por uma mais segura, a P2PKH.
* __Pay to Public Key Hash (P2PKH)__ - Uma transação padrão (```OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG```) que paga para o hash de uma chave pública.
* __Pay to Witness Public Key Hash (P2WPKH)__ - O tipo mais novo de transação de chave pública. Usa apenas (```OP_0 <pubKeyHash>```) porque depende do consenso do minerador para funcionar, conforme descrito na seção [§9.5](09_5_Scripting_a_P2WPKH.md).
* __Multisig__ - Uma transação para um grupo de chaves, conforme explicado mais detalhadamente na seção [§8.4](08_4_Scripting_a_Multisig.md).
* __Null Data__ - Uma transação que não pode ser gasta (`OP_RETURN Data`).
* __Pay to Script Hash (P2SH)__ - Uma transação que paga a um script específico, conforme explicado mais detalhadamente neste capítulo.
Então, como podemos descrever um script mais complexo do Bitcoin? A resposta está nesse último tipo de transação padrão, o P2SH. Podemos colocar qualquer tipo de script mais longo e complexo em uma transação P2SH e, contanto que sigamos as regras padrões para incorporar nosso script e resgatar os fundos, obteremos todos os benefícios do Script do Bitcoin.
> :warning: **AVISO DE VERSÃO:** Os Scripts P2SH somente se tornaram padrão à partir do Bitcoin Core 0.10.0. Antes disso, apenas os scripts do tipo P2SH Multisigs eram permitidos.
## Compreendendo o Script P2SH
Você já viu uma transação P2SH quando criou um multisig na seção [§6.1: Enviando uma Transação com Multisig](06_1_Sending_a_Transaction_to_a_Multisig.md). Embora o multisig seja um dos tipos de transação padrão, o ```bitcoin-cli``` simplifica o uso dos multisigs, incorporando-os às transações P2SH, conforme descrito mais detalhadamente na seção [§10.4: Programando um Multisig](10_4_Scripting_a_Multisig.md).
Então, vamos olhar mais uma vez para o ```scriptPubKey``` daquela transação multisig P2SH:
```
"scriptPubKey": {
"asm": "OP_HASH160 a5d106eb8ee51b23cf60d8bd98bc285695f233f3 OP_EQUAL",
"hex": "a914a5d106eb8ee51b23cf60d8bd98bc285695f233f387",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"2N8MytPW2ih27LctLjn6LfLFZZb1PFSsqBr"
]
}
```
O script de bloqueio tem uma aparência bastante simples: ```OP_HASH160 a5d106eb8ee51b23cf60d8bd98bc285695f233f3 OP_EQUAL```. Como de costume, há um grande bloco de dados no meio. Este é um hash de outro script de bloqueio que está oculto (```redeemScript```) que só será revelado quando os fundos forem resgatados. Em outras palavras, o script de bloqueio padrão para um endereço P2SH é: ```OP_HASH160 <redeemScriptHash> OP_EQUAL```.
> :book: ***O que é um redeemScript?*** Cada transação P2SH carrega a impressão digital de um script de bloqueio que fica oculto como um hash de 20 bytes. Quando uma transação P2SH é resgatada, o ```redeemScript``` completo (sem o hash) é incluído como parte do ```scriptSig```. O Bitcoin garantirá que o ```redeemScript``` corresponda ao hash. Então, ele realmente executa o ```redeemScript``` para ver se os fundos podem ser gastos (ou não).
Um dos elementos interessantes das transações P2SH é que nem o remetente nem o Blockchain sabem realmente o que é o ```redeemScript```! Um remetente simplesmente envia para um endereço P2SH padronizado que é marcado com um prefixo "2" e não se preocupa com a forma como o destinatário irá recuperar os fundos.
> :link: **TESTNET vs MAINNET:** Na testnet, o prefixo para endereços P2SH é ```2```, enquanto na mainnet, é ```3```.
## Compreendendo Como Construir um Script P2SH
Como o script de bloqueio está visível para uma transação P2SH e é bem simples, criar uma transação desse tipo também é um tanto quanto fácil. Em teoria. Tudo o que precisamos fazer é criar uma transação cujo script de bloqueio inclua um hash de 20 bytes do ```redeemScript```. Esse hash é feito com o padrão ```OP_HASH160``` do Bitcoin.
> :book: ***O que é OP_HASH160?*** Uma operação padrão do hash para o Bitcoin executar um hash SHA-256 e, em seguida, um hash RIPEMD-160.
No geral, quatro etapas são necessárias:
1. Criar um script de bloqueio arbitrário com Bitcoin Script;
2. Criar uma versão serializada desse script de bloqueio;
3. Executar um hash SHA-256 nesses bytes serializados;
4. Executar um hash RIPEMD-160 nos resultados desse hash SHA-256.
Cada uma dessas etapas exige algum trabalho e algumas delas podem ser bastante complexas. A boa notícia é que realmente não precisamos nos preocupar com elas, porque são complexas o suficiente para que tenhamos uma API que faz o serviço para nós, normalmente.
Por enquanto, forneceremos apenas uma visão geral, para que entendamos o contexto da metodologia. Na seção [§10.2: Construindo a Estrutura do P2SH](10_2_Building_the_Structure_of_P2SH.md), forneceremos uma visão mais aprofundada da criação do script, caso queiramos entender a essência desse processo.
## Compreendendo Como Enviar uma Transação P2SH
Então, como enviamos nossa transação P2SH? Novamente, a teoria é muito simples:
1. Incorporamos o hash em um script ```OP_HASH160 <redeemScriptHash> OP_EQUAL```;
2. Traduzimos isso para um código hexadecimal;
3. Usamos esse hex como nosso ```scriptPubKey```;
4. Criamos o resto da transação.
Infelizmente, este é outro momento em que precisaremos usar APIs, em grande parte porque o ```bitcoin-cli``` não fornece nenhum suporte para a criação de transações P2SH. Mas, podemos resgatá-las sem problema.
## Compreendendo Como Desbloquear uma Transação P2SH
O truque para resgatar uma transação P2SH é que o destinatário deve ter salvo o script secreto de bloqueio serializado que foi codificado para criar o endereço P2SH. Isso se chama ```redeemScript``` porque é o que o destinatário precisa para resgatar os fundos.
Um ```scriptSig``` de desbloqueio para uma transação P2SH tem o seguinte formato: ``` ... dados ... <redeemScript>```. Os ```dados``` devem ser _somente_ dados que são colocados na pilha, não operadores. O [BIP 16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki) os chama de assinaturas, mas isso não é um requisito real.
> :warning: **AVISO:** Embora assinaturas não sejam um requisito, um script P2SH na verdade não é muito seguro se não exigir pelo menos uma assinatura nas entradas. As razões para isso estão descritas na seção [§13.1: Escrevendo Scripts Quebra-Cabeças](13_1_Writing_Puzzle_Scripts.md).
Quando um UTXO é resgatado, ele é executado em duas rodadas de verificação:
1. Primeiro, o ```redeemScript``` no ```scriptSig``` está em hash e é comparado ao hash do script no ```scriptPubKey```;
2. Se eles corresponderem, uma segunda rodada de verificação será iniciada;
3. Em segundo lugar, o ```redeemScript``` é executado usando os dados anteriores que foram colocados na pilha;
4. Se a segunda rodada de verificação _também_ for bem-sucedida, o UTXO é desbloqueado.
Considerando que não podemos criar facilmente uma transação P2SH sem uma API, devemos ser capazes de resgatar facilmente uma transação P2SH com o ```bitcoin-cli```. Na verdade, já fizemos isso na seção [§6.2: Gastando uma Transação com Multisig](06_2_Spending_a_Transaction_to_a_Multisig.md). O processo exato é descrito na seção [§10.6: Gastando uma Transação P2SH](10_6_Spending_a_P2SH_Transaction.md), após terminarmos com todas as complexidades da criação de uma transação P2SH.
> :warning: **AVISO:** Podemos criar uma transação perfeitamente válida com um redeemScript com o hash correto, mas se o redeemScript não funcionar, ou não funcionar corretamente, os fundos serão perdidos para sempre. É por isso que é importantíssimo testar os scripts, conforme discutido na seção [§9.3: Testando um Script no Bitcoin](09_3_Testing_a_Bitcoin_Script.md).
## Resumo: Compreendendo a Base do P2SH
Scripts arbitrários não são o padrão no Bitcoin. No entanto, podemos incorporá-los em transações padrão usando o tipo de endereço P2SH. Precisamos apenas fazer um hash do nosso script como parte do script de bloqueio, então o revelamos e executamos como parte do script de desbloqueio. Contanto que também possamos satisfazer o ```redeemScript```, o UTXO poderá ser gasto.
> :fire: ***Qual é o poder do P2SH?*** Já sabemos o poder do Bitcoin Script, que nos permite criar Contratos Inteligentes mais complexos de todos os tipos. O P2SH é o que realmente libera esse poder, nos permitindo que incluamos o Script arbitrário do Bitcoin em transações padrão.
## O Que Vem Depois?
Vamos continuar "Incorporando Scripts em Transações P2SH no Bitcoin" na seção [§10.2: Construindo a Estrutura do P2SH](10_2_Building_the_Structure_of_P2SH.md).

View File

@ -0,0 +1,182 @@
# 10.2: Construindo a Estrutura do P2SH
Na seção anterior, apresentamos uma visão geral da teoria de como criar as transações P2SH para armazenar os scripts de Bitcoin. Na prática, fazer isso é _muito mais difícil_, mas por uma questão de integridade, vamos examinar minuciosamente todos os pontos. Provavelmente, isso não é algo que faríamos sem uma API, então, se ficar muito complicado, esteja ciente de que retornaremos aos scripts originais de alto nível mais pra frente.
## Criando um Script de Bloqueio
Qualquer transação P2SH começa com um script de bloqueio. Esse é o assunto dos capítulos 9, 11 e 12. Podemos usar qualquer um dos métodos de script do Bitcoin descritos nestes capítulos para criar qualquer tipo de script de bloqueio, desde que o ```redeemScript``` serializado resultante tenha 520 bytes ou menos.
> :book: ***Por que os scripts P2SH são limitados a 520 bytes?*** Como muitas coisas no Bitcoin, a resposta é a compatibilidade com as versões anteriores: novas funcionalidades devem ser constantemente criadas dentro das antigas restrições do sistema. Nesse caso, 520 bytes é o máximo que pode ser colocado na pilha de uma vez. Como todo o redeemScript é colocado na pilha como parte do processo de resgate, ele está limitado à essa quantidade.
## Serializando um Script de Bloqueio da Maneira Difícil
Depois de criar um script de bloqueio, precisamos serializá-lo antes que possam ser inseridos no Bitcoin. Este é um processo de duas partes. Primeiro, devemos transformá-lo em um hexcode, para então transformar esse hex em binário.
### Criando o Código Hexadecimal
Criar o hexcode necessário para serializar um script é uma simples tradução, mas ao mesmo tempo, algo complexo o suficiente para ir além de qualquer script shell que provavelmente escreveremos. Esta etapa é um dos principais motivos pelos quais precisamos de uma API para criar as transações P2SH.
Podemos criar um hexcode percorrendo nosso script de bloqueio e transformando cada elemento em um comando hexadecimal de um byte, possivelmente seguido por dados adicionais. De acordo com o guia da [página Wiki do Bitcoin Script](https://en.bitcoin.it/wiki/Script):
* Os operadores são traduzidos para o byte correspondente para esse opcode;
* As constantes 1-16 são convertidas para opcodes 0x51 a 0x61 (OP_1 a OP_16);
* A constante -1 é traduzida para opcode 0x4f (OP_1NEGATE);
* Outras constantes são precedidas por opcodes 0x01 a 0x4e (OP_PUSHDATA, com o número especificando de quantos bytes adicionar);
* Os inteiros são traduzidos em hexadecimal usando a notação de magnitude com sinal _little-endian_.
### Traduzindo os Números Inteiros
Os inteiros são a parte mais problemática de uma tradução de script de bloqueio.
Primeiro, devemos verificar se o nosso número está entre -2147483647 e 2147483647, o intervalo de inteiros de quatro bytes quando o byte mais significativo é usado para assinatura.
Em segundo lugar, precisamos traduzir o valor decimal em hexadecimal e preenchê-lo com um número par de dígitos. Isso pode ser feito com o comando ```printf```:
```
$ integer=1546288031
$ hex=$(printf '%08x\n' $integer | sed 's/^\(00\)*//')
$ echo $hex
5c2a7b9f
```
Terceiro, precisamos adicionar um byte inicial adicional de ```00``` se o dígito superior for "8" ou maior, para que o número não seja interpretado como negativo.
```
$ hexfirst=$(echo $hex | cut -c1)
$ [[ 0x$hexfirst -gt 0x7 ]] && hex="00"$hex
```
Quarto, precisamos traduzir o hexa em _big-endian_ (byte menos significativo por último) para _little-endian_ (byte menos significativo primeiro). Podemos fazer isso com o comando ```tac```:
```
$ lehex=$(echo $hex | tac -rs .. | echo "$(tr -d '\n')")
$ echo $lehex
9f7b2a5c
```
Além disso, sempre precisaremos saber o tamanho dos dados que colocamos na pilha, para que possamos precedê-los com o opcode adequado. Podemos apenas lembrar que cada dois caracteres hexadecimais é um byte. Ou podemos usar o comando ```echo -n``` com o pipe para ```wc -c``` e dividi-lo ao meio:
```
$ echo -n $lehex | wc -c | awk '{print $1/2}'
4
```
Com todo esse trabalho, iríamos saber que poderíamos traduzir o número inteiro 1546288031 em um opcode ```04``` (para colocar quatro bytes na pilha) seguido por ```9f7b2a5c``` (a representação hexadecimal do tipo _little-endian_ de 1546288031).
Se, ao invés disso, tivéssemos um número negativo, precisaríamos (1) fazer os cálculos no valor absoluto do número e, em seguida, (2) bit a bit - ou colocar 0x80 para nosso resultado _little-endian_ final. Por exemplo, ```9f7b2a5c```, que é 1546288031, se tornaria ```9f7b2adc```, que é -1546288031:
```
$ neglehex=$(printf '%x\n' $((0x$lehex | 0x80)))
$ echo $neglehex
9f7b2adc
```
### Transformando o Hex em Binário
Para completar nossa serialização, traduzimos o código hexadecimal em binário. Na linha de comando, isso requer apenas uma invocação simples do ```xxd -r -p```. No entanto, provavelmente desejamos fazer isso tudo junto, para também fazer o hash do script...
## Executando o Script de Conversão de Inteiros
Um script completo para alterar um número inteiro entre -2147483647 e 2147483647 para uma representação de magnitude assinada do tipo _little-endian_ em hexadecimal pode ser encontrado no [diretório de código src](../src/10_2_integer2lehex.sh). Podemos baixar o ```integeer2lehex.sh```.
> :warning: **AVISO:** Este script não foi verificado de forma consistente. Se formos utilizá-lo para criar scripts de bloqueio reais, precisamos nos certificar de verificar e testar os resultados.
Precisamos nos certificar de que as permissões no script estão corretas:
```
$ chmod 755 integer2lehex.sh
```
Podemos então executar o script da seguinte maneira:
```
$ ./integer2lehex.sh 1546288031
Integer: 1546288031
LE Hex: 9f7b2a5c
Length: 4 bytes
Hexcode: 049f7b2a5c
$ ./integer2lehex.sh -1546288031
Integer: -1546288031
LE Hex: 9f7b2adc
Length: 4 bytes
Hexcode: 049f7b2adc
```
## Analisando um Multisig P2SH
Para entender melhor o processo, faremos a engenharia reversa do multisig P2SH que criamos na seção [§6.1: Enviando uma Transação com Multisig](06_1_Sending_a_Transaction_to_a_Multisig.md). Dê uma olhada no ```redeemScript``` que usamos, que agora sabemos que é a versão hexadecimal do script de bloqueio:
```
522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae
```
Podemos traduzir isso de volta para o script manualmente usando a [página Wiki do Bitcoin Script](https://en.bitcoin.it/wiki/Script) como uma referência. Basta olhar para um byte (dois caracteres hexadecimais) de dados por vez, a menos que nos seja dito para olhar pra mais bytes usando OP_PUSHDATA (um opcode no intervalo de 0x01 a 0x4e).
Todo o Script será dividido da seguinte forma:
```
52 / 21 / 02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191 / 21 / 02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3 / 52 / ae
```
Aqui está o que cada parte individual significa:
* 0x52 = OP_2
* 0x21 = OP_PUSHDATA 33 bytes (hex: 0x21)
* 0x02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191 = os próximos 33 bytes (hash de chave pública)
* 0x21 = OP_PUSHDATA 33 bytes (hex: 0x21)
* 0x02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3 = os próximos 33 bytes (hash de chave pública)
* 0x52 = OP_2
* 0xae = OP_CHECKMULTISIG
Em outras palavras, esse ```redeemScript``` era uma tradução de ```2 02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191 02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3 2 OP_CHECKMULTISIG```. Voltaremos a este script na seção [§10.4: Programando um Multisig](10_4_Scripting_a_Multisig.md) quando detalharmos exatamente como os multisigs funcionam dentro do paradigma P2SH.
Se gostarmos de fazer o trabalho manual com esse tipo de tradução no futuro, podemos usar o ```decodescript bitcoin-cli```:
```
$ bitcoin-cli -named decodescript hexstring=522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae
{
"asm": "2 02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191 02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3 2 OP_CHECKMULTISIG",
"reqSigs": 2,
"type": "multisig",
"addresses": [
"mmC2x2FoYwBnVHMPRUAzPYg6WDA31F1ot2",
"mhwZFJUnWqTqy4Y7pXVum88qFtUnVG1keM"
],
"p2sh": "2N8MytPW2ih27LctLjn6LfLFZZb1PFSsqBr",
"segwit": {
"asm": "0 6fe9f451ccedb8e4090b822dcad973d0388a37b4c89fd1aed485110adecab2a9",
"hex": "00206fe9f451ccedb8e4090b822dcad973d0388a37b4c89fd1aed485110adecab2a9",
"reqSigs": 1,
"type": "witness_v0_scripthash",
"addresses": [
"tb1qdl5lg5wvakuwgzgtsgku4ktn6qug5da5ez0artk5s5gs4hk2k25szvjky9"
],
"p2sh-segwit": "2NByn92W1vH5oQC1daY69F5sU7PEStKKQBR"
}
}
```
É especialmente útil para verificar nosso trabalho durante a serialização.
## Serializando um Script de Bloqueio da Maneira Fácil
Quando instalamos o ```btcdeb``` na seção [§9.3](09_3_Testing_a_Bitcoin_Script.md) também instalamos o ```btcc``` que pode ser usado para serializar scripts do Bitcoin:
```
$ btcc 2 02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191 02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3 2 OP_CHECKMULTISIG
warning: ambiguous input 2 is interpreted as a numeric value; use OP_2 to force into opcode
warning: ambiguous input 2 is interpreted as a numeric value; use OP_2 to force into opcode
522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae
```
Isso é muito mais fácil do que fazer tudo na mão!
Considere também o compilador em Python, [Transaction Script Compiler](https://github.com/Kefkius/txsc), que traduz de trás pra frente também.
## Fazendo o Hash de um Script Serializado
Depois de criar um script de bloqueio e serializá-lo, a terceira etapa na criação de uma transação P2SH é fazer o hash do script de bloqueio. Conforme observado anteriormente, um hash OP_HASH160 de 20 bytes é criado por meio de uma combinação de um hash SHA-256 e um hash RIPEMD-160. O hash de um script serializado, portanto, requer dois comandos: ```openssl dgst -sha256 -binary``` que faz o hash SHA-256 e produz um binário a ser enviado no pipe, então o ```openssl dgst -rmd160``` pega o fluxo do binário, faz um RIPEMD- 160 hash e, finalmente, gera um código hexadecimal legível.
Aqui está todo o processo, incluindo a transformação anterior do script hexadecimal em binário:
```
$ redeemScript="522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae"
$ echo -n $redeemScript | xxd -r -p | openssl dgst -sha256 -binary | openssl dgst -rmd160
(stdin)= a5d106eb8ee51b23cf60d8bd98bc285695f233f3
```
## Criando uma Transação P2SH
Criar o hash de 20 bytes apenas fornece o hash no centro de um script de bloqueio P2SH. Ainda precisamos colocá-lo junto com os outros opcodes que criam uma transação P2SH padrão: ```OP_HASH160 a5d106eb8ee51b23cf60d8bd98bc285695f233f3 OP_EQUAL```.
Dependendo de nossa API, podemos inserir isso como um ```scriptPubKey``` no estilo ```asm``` para nossa transação, ou podemos ter que traduzi-lo para o código ```hex``` também. Se tivermos que traduzir, podemos usar os mesmos métodos descritos acima para "Criar o código hexadecimal" (ou usar o ```btcc```), resultando em ```a914a5d106eb8ee51b23cf60d8bd98bc285695f233f387```.
Podemos observar que o ```hex scriptPubKey``` para a transação P2SH Script irá _sempre_ começar com um ```a914```, que é o ```OP_HASH160``` seguido por um ```OP_PUSHDATA``` de 20 bytes (hex: ```0x14```); e _sempre_ terminará com um ```87```, que é um ```OP_EQUAL```. Portanto, tudo o que precisamos fazer é colocar o script de resgate em hash entre esses números.
## Resumo: Construindo a Estrutura do P2SH
Na verdade, a criação do script de bloqueio P2SH entra ainda mais nas entranhas do Bitcoin. Embora seja útil saber como tudo isso funciona em um nível muito baixo, é mais provável que tenhamos uma API cuidando de todo o trabalho pesado para nós. Nossa tarefa será simplesmente criar o Script Bitcoin para fazer o bloqueio... que é o tópico principal dos capítulos 9, 11 e 12.
## O Que Vem Depois?
Vamos continuar "Incorporando Scripts em Transações P2SH no Bitcoin" na seção [§10.3: Executando um Script no Bitcoin com P2SH](10_3_Running_a_Bitcoin_Script_with_P2SH.md).

View File

@ -0,0 +1,99 @@
# 10.3: Executando um Script no Bitcoin com P2SH
Agora que conhecemos a teoria e a prática por trás dos endereços P2SH, estamos prontos para transformar um script de Bitcoin não-padrão em uma transação real. Vamos utilizar o script de bloqueio simples da seção [§9.2: Executando um Script no Bitcoin](09_2_Running_a_Bitcoin_Script.md), `OP_ADD 99 OP_EQUAL`.
## Criando uma Transação P2SH
Para bloquear uma transação com este script, precisamos fazer o seguinte:
1. Serializar o `OP_ADD 99 OP_EQUAL`:
1. OP_ADD = 0x93 - uma tradução simples do opcode;
2. 99 = 0x01, 0x63 - este opcode coloca um byte na pilha, 99 (hex: 0x63);
* Não se preocupe com a conversão porque é apenas um byte.
3. OP_EQUAL = 0x87 - uma tradução simples do opcode;
4. ```<serialized99Equal>``` = "93016387".
```
$ btcc OP_ADD 99 OP_EQUAL
93016387
```
2. Vamos salvar o ```<serialized99Equal>``` para referência futura como ```redeemScript```;
1. `<redeemScript>` = "93016387".
3. SHA-256 e RIPEMD-160 do hash do script serializado;
1. ```<hashed99Equal>``` = "3f58b4f7b14847a9083694b9b3b52a4cea2569ed".
4. Produzir um script de bloqueio P2SH que inclua o ```<hashed99Equal>```;
1. ```scriptPubKey``` ="a9143f58b4f7b14847a9083694b9b3b52a4cea2569ed87".
Podemos então criar uma transação usando o ```scriptPubKey```, provavelmente através de uma API.
## Desbloqueando a Transação P2SH
Para desbloquear essa transação, é necessário que o destinatário produza um ```scriptSig``` que acrescente duas constantes, totalizando noventa e nove, ao script serializado:```1 98 <serialized99Equal>```.
### Executando a Primeira Rodada de Validação
O processo de desbloqueio da transação P2SH começa com uma primeira rodada de validação, que nada mais é que a verificação se o script de resgate corresponde ao valor hash no script de bloqueio.
Vamos concatenar o ```scriptSig``` e o ```scriptPubKey``` e executá-los, normalmente:
```
Script: 1 98 <serialized99Equal> OP_HASH160 <hashed99Equal> OP_EQUAL
Stack: []
Script: 98 <serialized99Equal> OP_HASH160 <hashed99Equal> OP_EQUAL
Stack: [ 1 ]
Script: <serialized99Equal> OP_HASH160 <hashed99Equal> OP_EQUAL
Stack: [ 1 98 ]
Script: OP_HASH160 <hashed99Equal> OP_EQUAL
Stack: [ 1 98 <serialized99Equal> ]
Script: <hashed99Equal> OP_EQUAL
Running: <serialized99Equal> OP_HASH160
Stack: [ 1 98 <hashed99Equal> ]
Script: OP_EQUAL
Stack: [ 1 98 <hashed99Equal> <hashed99Equal> ]
Script:
Running: <hashed99Equal> <hashed99Equal> OP_EQUAL
Stack: [ 1 98 True ]
```
O script termina com um ```True``` no topo da pilha e, portanto, foi bem-sucedido... embora haja outro fragmento abaixo dele.
Porém, por se tratar de um script P2SH, a execução não está concluída.
### Executando a Segunda Rodada de Validação
Para a segunda rodada de validação, vamos verificar se os valores no script de desbloqueio satisfazem o ```redeemScript```: desserializando o ```redeemScript``` ("93016387" = "OP_ADD 99 OP_EQUAL") e executando-o usando os itens no ```scriptSig``` anterior para o script serializado:
```
Script: 1 98 OP_ADD 99 OP_EQUAL
Stack: [ ]
Script: 98 OP_ADD 99 OP_EQUAL
Stack: [ 1 ]
Script: OP_ADD 99 OP_EQUAL
Stack: [ 1 98 ]
Script: 99 OP_EQUAL
Running: 1 98 OP_ADD
Stack: [ 99 ]
Script: OP_EQUAL
Stack: [ 99 99 ]
Script:
Running: 99 99 OP_EQUAL
Stack: [ True ]
```
Com essa segunda validação _também_ verdadeira, o UTXO agora pode ser gasto!
## Resumo: Executando um Script no Bitcoin com P2SH
Depois de conhecer a técnica de construção dos P2SH, qualquer script pode ser embutido em uma transação Bitcoin, e depois de entender a técnica de validação do P2SH, é fácil executar os scripts em duas fases.
## O Que Vem Depois?
Vamos continuar "Incorporando Scripts em Transações P2SH no Bitcoin" na seção [§10.4: Programando um Multisig](10_4_Scripting_a_Multisig.md).

View File

@ -0,0 +1,150 @@
# 10.4: Programando um Multisig
Antes de encerrarmos esta introdução ao script P2SH, vale a pena examinar um exemplo mais realista. Desde a seção [§6.1](06_1_Sending_a_Transaction_to_a_Multisig.md), dissemos casualmente que a interface ```bitcoin-cli``` envolve nossa transação multisig em uma transação P2SH. Na verdade, esta é a metodologia padrão para a criação dos multisigs na Blockchain do Bitcoin. Veja como isso funciona, com mais detalhes.
## Compreendendo o Código Multisig
As transações multisig são criadas no Bitcoin usando o código ```OP_CHECKMULTISIG```. O ```OP_CHECKMULTISIG``` espera uma longa sequência de argumentos que se parece com isto: ```0 ... sigs ... <m> ... endereços ... <n> OP_CHECKMULTISIG```. Quando o ```OP_CHECKMULTISIG``` é executado, ele faz o seguinte:
1. Retira o primeiro valor da pilha (```<n>```);
2. Retira "n" valores da pilha como endereços Bitcoin (hash de chaves públicas);
3. Retira o próximo valor da pilha (```<m>```);
4. Retira "m" valores da pilha como assinaturas potenciais;
5. Retira um `0` da pilha devido a um erro na codificação original;
6. Compara as assinaturas com os endereços de Bitcoin;
7. Coloca ```True``` ou ```False``` dependendo do resultado.
Os operandos do ```OP_MULTISIG``` são tipicamente divididos, com o ```0``` e as assinaturas vindo do script de desbloqueio e o "m", "n" e endereços sendo detalhados pelo script de bloqueio.
O requisito para que o ```0``` seja o primeiro operando para o ```OP_CHECKMULTISIG``` é uma regra de consenso. Como a versão original do ```OP_CHECKMULTISIG``` acidentalmente retirou um item extra da pilha, o Bitcoin deve seguir esse padrão para sempre, para que os scripts de resgate complexos daquele período de tempo não sejam acidentalmente quebrados, tornando fundos antigos irrecuperáveis.
> :book: ***O que é uma regra de consenso?*** Estas são as regras que os nodes do Bitcoin seguem para trabalharem juntos. Em grande parte, eles são definidos pelo código do Bitcoin Core. Essas regras incluem muitas regras óbvias, como o limite de quantos Bitcoins são criados para cada bloco e as regras de como as transações podem ser respondidas. No entanto, eles também incluem correções para bugs que apareceram ao longo dos anos, porque uma vez que um bug foi introduzido na base de código do Bitcoin, ele deve ser continuamente suportado, para que os antigos bitcoins não se tornem impossíveis de serem gastos.
## Criando um Multisig Bruto
Conforme discutido na seção [§10.2: Construindo a Estrutura do P2SH](10_2_Building_the_Structure_of_P2SH.md), os multisigs são um dos tipos de transação padrão do Bitcoin. Uma transação pode ser criada com um script de bloqueio que usa o comando ```OP_CHECKMULTISIG``` bruto e será aceita em um bloco. Esta é a metodologia clássica para usar multisigs no Bitcoin.
Como exemplo, iremos revisitar o multisig criado na seção [§8.1](08_1_Sending_a_Transaction_with_a_Locktime.md) uma última vez e construir um novo script de bloqueio para ele usando esta metodologia. Como devemos nos lembrar, essa transação era uma multisig 2 de 2 construída a partir de ```$address1``` e ```$address2```.
Como o script de bloqueio ```OP_CHECKMULTISIG``` requer o "m" (```2```), os endereços, e o "n" (```2```), poderíamos escrever o seguinte ```scriptPubKey```:
```
2 $address1 $address2 2 OP_CHECKMULTISIG
```
Se isso parece familiar, é porque é o multisig que desserializamos no [§10.2: Construindo a Estrutura do P2SH](10_2_Building_the_Structure_of_P2SH.md).
```
2 02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191 02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3 2 OP_CHECKMULTISIG
```
> **AVISO:** Para assinaturas `OP_CHECKMULTISIG` clássicas, o "n" deve ser ≤ 3 para que a transação seja padrão.
## Desbloqueando um Multisig Bruto
O ```scriptSig``` para um endereço multisig padrão deve então enviar os operandos ausentes para o ```OP_CHECKMULTISIG```: um ```0``` seguido por "m" assinaturas. Por exemplo:
```
0 $signature1 $signature2
```
### Executando um Script Multisig Bruto
Para gastar um UTXO multisig, executamos o ```scriptSig``` e o ```scriptPubKey``` da seguinte maneira:
```
Script: 0 $signature1 $signature2 2 $address1 $address2 2 OP_CHECKMULTISIG
Stack: [ ]
```
Primeiro, colocamos todas as constantes na pilha:
```
Script: OP_CHECKMULTISIG
Stack: [ 0 $signature1 $signature2 2 $address1 $address2 2 ]
```
Então, o ```OP_CHECKMULTISIG``` começa a rodar. Primeiro, o "2" é retirado:
```
Running: OP_CHECKMULTISIG
Stack: [ 0 $signature1 $signature2 2 $address1 $address2 ]
```
Então, o "2" diz ao ```OP_CHECKMULTISIG``` para retirar dois endereços:
```
Running: OP_CHECKMULTISIG
Stack: [ 0 $signature1 $signature2 2 ]
```
Então, o próximo "2" é retirado:
```
Running: OP_CHECKMULTISIG
Stack: [ 0 $signature1 $signature2 ]
```
Então, o "2" diz ao ```OP_CHECKMULTISIG``` para retirar duas assinaturas:
```
Running: OP_CHECKMULTISIG
Stack: [ 0 ]
```
Então, mais um item é retirado por engano:
```
Running: OP_CHECKMULTISIG
Stack: [ ]
```
Depois, o ```OP_CHECKMULTISIG``` completa a operação comparando as "m" assinaturas aos "n" endereços:
```
Script:
Stack: [ True ]
```
## Compreendendo as Limitações dos Scripts Multisig Brutos
Infelizmente, a técnica de incorporar um multisig bruto em uma transação tem algumas desvantagens notáveis:
1. Como não há formato de endereço padrão para os multisigs, cada remetente deve: inserir um script multisig longo e complicado; ter um software que permite fazer isso; e ser confiável para não bagunçar nada.
2. Como os multisigs podem ser muito mais longos do que os scripts padrão de bloqueio, a blockchain aumenta o custo. Isso requer taxas de transação mais altas para o remetente e cria mais incômodo para cada node.
Geralmente, esses eram problemas com qualquer tipo de script complexo do Bitcoin, mas rapidamente se tornaram problemas muito reais quando aplicados aos multisigs, que foram alguns dos primeiros scripts complexos a serem amplamente usados na rede Bitcoin. As transações P2SH foram criadas para resolver esses problemas, começando em 2012.
> :book: ***O que é um multisig P2SH?*** Os Multisigs P2SH foram a primeira implementação de transações P2SH. Eles simplesmente empacotam uma transação multisig padrão em uma transação P2SH padrão. Isso permite a padronização de endereços, reduz o armazenamento de dados e, aumenta as contagens "m" e "n".
## Criando um Multisig P2SH
Os Multisigs P2SH são a metodologia moderna para a criação de multisigs na Blockchain. Elas podem ser criadas de forma muito simples, usando o mesmo processo visto nas seções anteriores.
### Criando um Bloqueio para o Multisig P2SH
Para criar um multisig P2SH, siga as etapas padrão para criar um script de bloqueio P2SH:
1. Serializar ```2 $ address1 $ address2 2 OP_CHECKMULTISIG```;
1. ```<serializedMultiSig>``` = "522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98dfaed8d287f76c570e98dfaed8d287f76c570123582e38ed8287fab56c570123582e38ed8287fab56.
2. Salvar o ```<serializedMultiSig>``` para referência futura como o redemScript;
1. ```<redeemScript>``` = "522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae".
3. Fazer o hash SHA-256 e RIPEMD-160 do script serializado;
1. `<hashedMultiSig>` = "a5d106eb8ee51b23cf60d8bd98bc285695f233f3".
4. Produzir um script de bloqueio P2SH Multisig que inclua o hash do script (```OP_HASH160 <hashedMultisig> OP_EQUAL```).
1. ```scriptPubKey``` =" a914a5d106eb8ee51b23cf60d8bd98bc285695f233f387 ".
Você pode criar uma transação usando o ```scriptPubKey```.
## Desbloqueando o Multisig P2SH
Para desbloquear essa transação multisig, é necessário que o destinatário produza um scriptSig que inclua as duas assinaturas e o ```redeemScript```.
### Executando a Primeira Rodada de Validação do P2SH
Para desbloquear o multisig P2SH, primeiro vamos confirmar o script:
1. Produzir um script de desbloqueio de ```0 $ signature1 $ signature2 <serializedMultiSig>```;
2. Concatenar isso com o script de bloqueio ```OP_HASH160 <hashedMultisig> OP_EQUAL```;
3. Validar o ```0 $ assinatura1 $ assinatura2 <serializedMultiSig> OP_HASH160 <hashedMultisig> OP_EQUAL```;
4. Teremos êxito se o ```<serializedMultisig>``` corresponder ao ```<hashedMultisig>```.
### Executando a Segunda Rodada de Validação do P2SH
Em seguida, vamos executar o script multisig:
1. Desserializar o ```<serializedMultiSig>``` para ```2 $ address1 $ address2 2 OP_CHECKMULTISIG```;
2. Concatenar isso com os operandos anteriores no script de desbloqueio, ```0 $ assinatura1 $ assinatura2```;
3. Validar o ```0 $ assinatura1 $ assinatura2 2 $ endereço1 $ endereço2 2 OP_CHECKMULTISIG```;
4. Teremos sucesso se os operandos cumprirem o ```redemScript``` desserializado.
Agora sabemos como a transação multisig da seção [§6.1](06_1_Sending_a_Transaction_to_a_Multisig.md) foi realmente criada, como foi validada para ser gasta e o motivo pelo qual o ```redeemScript``` foi tão importante.
## Resumo: Programando um Multisig
Os multisigs são um tipo de transação padrão, mas são um pouco complicados de serem usados. Então, eles são regularmente incorporados em transações P2SH, como foi o caso na seção [§6.1](06_1_Sending_a_Transaction_to_a_Multisig.md) quando criamos nossos primeiros multisigs. O resultado é mais limpo, menor e mais padronizado, porém, e mais importante, é um ótimo exemplo do mundo real de como os scripts P2SH realmente funcionam.
## O Que Vem Depois?
Vamos continuar "Incorporando Scripts em Transações P2SH no Bitcoin" na seção [§10.5: Programando um Script Segwit](10_5_Scripting_a_Segwit_Script.md).

View File

@ -0,0 +1,127 @@
# 10.5: Programando um Script Segwit
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
O Segwit introduziu uma série de novas opções para tipos de endereço e também de scripts. Na seção [§9.5: Programando um P2WPKH](09_5_Scripting_a_P2WPKH.md) explicamos como o novo tipo de endereço Bech32 variou os scripts padrão encontrados na maioria das transações tradicionais. Este capítulo examina os três outros tipos de scripts introduzidos pela atualização do Segwit: o P2SH-Segwit (que era o endereço "nested Segwit" de transição, quando o Segwit passou a ser usado), o P2WSH (que é o Segwit equivalente ao endereço P2SH , assim como P2WPKH é o Segwit equivalente ao endereço P2PKH) e o endereço nested P2WSH.
Esta é outra situação onde realmente não teremos que nos preocupar com os nuances ao trabalhar com o ```bitcoin-cli```, mas é útil saber como tudo funciona.
## Compreendendo um Script P2SH-Segwit
O endereço P2SH-Segwit é um tipo em extinção. Foi basicamente uma medida paliativa enquanto o Bitcoin fazia a transição para o Segwit que permitia a um usuário criar um endereço Segwit e, em seguida, alguém como uma exchange que ainda não habilitou o Segwit ou carteira antiga financiasse esse endereço.
Se precisarmos usar um, há uma opção para criar um endereço P2SH-Segwit usando ```getnewaddress```:
```
$ bitcoin-cli getnewaddress -addresstype p2sh-segwit
2NEzBvokxh4ME4ahdT18NuSSoYvvhS7EnMU
```
O endereço começa com um ```2``` (ou ```3```) revelando-o como um script.
> :book: ***Por que os nodes antigos não podem enviar para endereços Segwit nativos?*** Na seção [§10.1](10_1_Understanding_the_Foundation_of_P2SH.md) observamos que havia um número definido de transações padrão no Bitcoin. Na verdade, não podemos bloquear uma transação com um script que não seja um desses tipos padrão. O Segwit agora é reconhecido como um desses padrões, mas um node antigo não saberá disso e, portanto, se recusará a enviar tal transação para a proteção daquele que o está enviando. Encapsular um endereço Segwit dentro de um script padrão em hash resolve o problema.
Quando você olha para um UTXO enviado para esse endereço, pode ver que o ```desc``` é diferente, revelando um endereço WPKH envolto em um script:
```
$ bitcoin-cli listunspent
{
"txid": "ed752673bfd4338ccf0995983086da846ad652ae0f28280baf87f9fd44b3c45f",
"vout": 1,
"address": "2NEzBvokxh4ME4ahdT18NuSSoYvvhS7EnMU",
"redeemScript": "001443ab2a09a1a5f2feb6c799b5ab345069a96e1a0a",
"scriptPubKey": "a914ee7aceea0865a05a29a28d379cf438ac5b6cd9c687",
"amount": 0.00095000,
"confirmations": 1,
"spendable": true,
"solvable": true,
"desc": "sh(wpkh([f004311c/0'/0'/3']03bb469e961e9a9cd4c23db8442d640d9b0b11702dc0126462ac9eb88b64a4dd48))#p29e839h",
"safe": true
}
```
Mais importante ainda, é a presença de um ```redeemScript```, que decodifica para ```OP_0 OP_PUSHDATA (20 bytes) 3ab2a09a1a5f2feb6c799b5ab345069a96e1a0a```. Isso deve parecer familiar, porque é um ```OP_0``` seguido por um hexcode de 20 bytes de um hash de chave pública. Em outras palavras, um P2SH-SegWit é apenas um SegWit ```scriptPubKey``` preso em um script. Isso é tudo que há para fazer. Corresponde precisamente ao modo como os multisigs modernos são um multsig preso em um P2SH, conforme discutido na seção [§10.4: Programando um Multisig](10_4_Scripting_a_Multisig.md).
A transação bruta revela um pouco mais de detalhes quando olhamos para o ```vout``` ```1```:
```
$ hex=$(bitcoin-cli gettransaction "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa" | jq -r '.hex')
$ bitcoin-cli decoderawtransaction $hex
{
"txid": "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa",
"hash": "6866490b16a92d68179e1cf04380fd08f16ec80bf66469af8d5e78ae624ff202",
"version": 2,
"size": 249,
"vsize": 168,
"weight": 669,
"locktime": 1780788,
"vin": [
{
"txid": "4779bb137ddbcaf796f905e264554b1ec28c0f3ab4538ca02eac5099bfc3fc1e",
"vout": 0,
"scriptSig": {
"asm": "0014c4ea10874ae77d957e170bd43f2ee828a8e3bc71",
"hex": "160014c4ea10874ae77d957e170bd43f2ee828a8e3bc71"
},
"txinwitness": [
"3044022025ee4fd38e6865125f7c315406c0b3a8139d482e3be333727d38868baa656d3d02204b35d9b5812cb85894541da611d5cec14c374ae7a7b8ba14bb44495747b5715301",
"033cae26cb3fa063c95e2c55a94bd04ab9cf173104555efe448b1bfc3a68c8f873"
],
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.00095000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 41d83eaffbf80f82dee4c152de59a38ffd0b6021 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a91441d83eaffbf80f82dee4c152de59a38ffd0b602188ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"mmX7GUoXq2wVcbnrnFJrGKsGR14fXiGbD9"
]
}
},
{
"value": 0.01063793,
"n": 1,
"scriptPubKey": {
"asm": "OP_HASH160 b780fc2e945bea71b9ee2d8d2901f00914a25fbd OP_EQUAL",
"hex": "a914b780fc2e945bea71b9ee2d8d2901f00914a25fbd87",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"2N9yWARt5E3TQsX2RjsauxSZaEZVhinAS4h"
]
}
}
]
}
```
Isso confirma que este é apenas um P2SH normal, bloqueado por ```"OP_DUP OP_HASH160 41d83eaffbf80f82dee4c152de59a38ffd0b6021 OP_EQUALVERIFY OP_CHECKSIG"```. É quando o script de resgate é executado que a mágica ocorre. Assim como com um P2WPKH, um node antigo verá ```OP_0 OP_PUSHDATA (20 bytes) 3ab2a09a1a5f2feb6c799b5ab345069a96e1a0a``` e verificará automaticamente, enquanto um novo node verá isso, saberá que é um P2WPKH e, assim, irá verificar o ```witness```. Podemos consultar isso na seção [§9.5: Programando um P2WPKH](09_5_Scripting_a_P2WPKH.md).
> :book: ***Quais são as desvantagens das transações nested Segwit?*** Elas são maiores do que as transações Segwit nativas, então temos algumas das vantagens do Segwit, mas não todas.
## Compreendendo um Script P2WSH
Ao contrário, as transações P2WSH devem ser cada vez mais utilizadas, uma vez que são a substituição do Segwit nativo para o P2SH, oferecendo todas as mesmas vantagens de tamanho de bloco que foram criadas com transações Segwit P2WPKH nativas.
Este é um exemplo de endereço P2WSH:
[https://mempool.space/pt/testnet/address/tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7](https://blockstream.info/testnet/address/tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7).
Os detalhes mostram que um UTXO enviado para este endereço está bloqueado com um ```scriptPubKey``` como este:
```
OP_0 OP_PUSHDATA (32 bytes) 1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262
```
O funcionamento é exatamente como um endereço P2WPKH, a única diferença é que ao invés de um hash de chave pública de 20 bytes, o UTXO inclui um hash de script de 32 bytes. Assim como com um P2WPKH, os nodes antigos apenas verificam isso, enquanto os novos nodes reconhecem que se trata de um P2WSH e verificam internamente o script conforme descrito nas seções anteriores, mas usando os dados da ```witness```, que agora incluem o script de resgate.
Há também mais uma variante, um script P2WSH embutido em um script P2SH, que funciona muito como o P2SH-Segwit descrito acima, mas para scripts P2WSH aninhados. (Ufa!)
## Resumo: Programando um Script Segwit
Existem dois tipos de scripts P2SH relacionados ao Segwit.
O endereço P2SH-Segwit é um endereço nested Segwit que incorpora o Segwit ```scriptPubkey``` simples dentro de um Script, assim como multisigs são incorporados nos scripts hoje em dia: a chave do tipo Segwit é desenrolada e então analisada normalmente em uma máquina que entende o Segwit . O objetivo é a compatibilidade com versões anteriores dos nodes antigos que, de outra forma, não seriam capazes de enviar saldos para endereços Segwit nativos.
O endereço P2WSH é uma variante Segwit de P2SH, assim como P2WPKH é uma variante Segwit de P2WSH. Ele funciona com a mesma lógica e é identificado por ter um hash de 32 bytes em vez de um hash de 20 bytes. O objetivo é estender as vantagens do Segwit a outros tipos de scripts.
## O Que Vem Depois?
Vamos continuar "Incorporando Scripts em Transações P2SH no Bitcoin" na seção [§10.6: Gastando uma Transação P2SH](10_6_Spending_a_P2SH_Transaction.md).

View File

@ -0,0 +1,42 @@
# 10.6: Gastando uma Transação P2SH
Antes de encerrarmos esta visão geral das transações P2SH, vamos abordar como gastá-las. Esta seção é principalmente uma visão geral, referindo-se a uma seção anterior onde _já_ gastamos uma transação P2SH.
## Usando o Script de Resgate
Como vimos na seção [§6.2: Gastando uma Transação com Multsig](06_2_Spending_a_Transaction_to_a_Multisig.md), gastar uma transação P2SH tem tudo a ver com ter aquela versão serializada do script de bloqueio, o chamado _redeemScript_. Portanto, o primeiro passo para poder gastar uma transação P2SH é ter certeza de salvar o _redeemScript_ antes de fornecer o endereço P2SH para todos.
### Coletando as Variáveis
Como endereços P2SH além dos endereços especiais multisig e nested Segwit não estão integrados no ```bitcoin-cli```, não haverá atalhos para gastarmos o P2SH como vimos na seção [§6.3: Enviando e Gastando um Multisig de Maneira Automatizada](6_3_Sending_an_Automated_Multisig.md) . Vamos precisar coletar todas as variáveis mais complexas por conta própria!
Isso significa que precisaremos coletar:
* O ```hex``` do ```scriptPubKey``` para a transação que estamos gastando;
* O ```redeemScript``` serializado;
* Quaisquer chaves privadas, já que assinaremos manualmente;
* Todos os ```txids```,```vouts``` e ```addresses``` regulares que precisarmos.
## Criando a Transação
Como vimos na seção §6.2, a criação de uma transação é bem padrão:
```
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.00005}''')
$ echo $rawtxhex
020000000121654fa95d5a268abf96427e3292baed6c9f6d16ed9e80511070f954883864b10000000000ffffffff0188130000000000001600142c48d3401f6abed74f52df3f795c644b4398844600000000
```
No entanto, a assinatura requer a inserção de informações extras para o (1) ```scriptPubKey```; (2) o ```redeemScript``` e; (3) quaisquer chaves privadas necessárias.
Aqui está o exemplo de como fazer isso para aquele multisig P2SH integrado na seção §6.2:
```
$ bitcoin-cli -named signrawtransactionwithkey hexstring=$rawtxhex prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cNPhhGjatADfhLD5gLfrR2JZKDE99Mn26NCbERsvnr24B3PcSbtR"]'
```
Com qualquer outro tipo de P2SH, incluiremos um ```redeemscript``` diferente, mas, fora isso, a prática é exatamente a mesma. A única diferença é que depois de dois capítulos de trabalho com scripts agora entendemos o que é o ```scriptPubKey``` e o que é o ```redeemScript```, então, esperançosamente, o que eram elementos misteriosos a quatro capítulos atrás, agora não são tão misteriosos assim.
## Resumo: Gastando uma Transação P2SH
Já gastamos um P2SH no Capítulo 6, quando reenviamos uma transação multsig da maneira mais difícil, que exigia alinhar as informações do ```scriptPubKey``` e do ```redeemScript```. Agora sabemos que o ```scriptPubKey``` é um script de bloqueio P2SH padronizado, enquanto o ```redeemScript``` corresponde a um hash naquele script de bloqueio e que precisamos ser capazes de executá-lo com as variáveis adequadas para receber um resultado ```True```. Mas além disso, não há nada de novo ao gastar uma transação P2SH, porque já fizemos isso!
## O Que Vem Depois?
Vamos avançar com "Programando Bitcoin" no [Capítulo 11: Capacitando Timelock com Scripts no Bitcoin](11_0_Empowering_Timelock_with_Bitcoin_Scripts.md).

View File

@ -0,0 +1,23 @@
# Capítulo 11: Capacitando Timelock com Scripts do Bitcoin
O recurso ```nLockTime``` da seção [§8.1](08_1_Sending_a_Transaction_with_a_Locktime.md) foi apenas o começo dos Timelocks. Quando começamos a escrever scripts do Bitcoin, dois opcodes de timelocks ficam disponíveis.
## Objetivos deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Decidir qual Timelock usar;
* Criar scripts com CLTV;
* Criar scripts com CSV.
Os objetivos secundários do capítulo incluem a capacidade de:
* Compreender as diferenças entre os diferentes timelocks;
* Gerar tempos relativos.
## Índice
* [Seção 1: Compreendendo As Opções de Timelock](11_1_Understanding_Timelock_Options.md)
* [Seção 2: Usando CLTV em Scripts](11_2_Using_CLTV_in_Scripts.md)
* [Seção 3: Usando CSV em Scripts](11_3_Using_CSV_in_Scripts.md)

View File

@ -0,0 +1,49 @@
# 11.1: Compreendendo As Opções de Timelock
Na seção [§8.1: Enviando uma transação com Locktime](08_1_Sending_a_Transaction_with_a_Locktime.md), o ```nLocktime``` ofereceu uma ótima opção inicial para bloquear as transações para que não pudessem ser gastas até algum ponto no futuro, com base no tempo (data/hora) ou na altura do bloco. Mas, essa não é a única maneira de colocar um timelock em uma transação.
## Compreendendo as Limitações do nLockTime
O ```nLockTime``` é uma maneira simples e poderosa de bloquear uma transação, mas possui algumas limitações:
1. **Sem divisões.** O `nLocktime` bloqueia toda a transação;
2. **Sem rede.** A maioria dos nodes modernos não aceita um ```nLockTime``` na mempool até que esteja na hora ou próximo para ser finalizada;
3. **Sem Scripts.** O uso simples e original do ```nLockTime``` não permitia que fosse usado em Scripts;
4. **Sem proteção.** O ```nLockTime``` permite que os fundos sejam gastos com uma transação diferente e não bloqueada.
O último item costumava ser o _dealbreaker_ para o ```nLockTime```. Isso evitou que uma transação fosse gasta, mas não impediu que os fundos fossem usados em uma transação diferente. Então, havia certos usos, mas todos dependiam de confiança.
## Compreendendo as Possibilidades dos Scripts de Timelock
Nos últimos anos, o Bitcoin Core foi expandido para permitir a manipulação dos timelocks no nível do opcode com os _OP_CHECKLOCKTIMEVERIFY_ (CLTV) e _OP_CHECKSEQUENCEVERIFY_ (CSV). Ambos trabalham sob uma nova metodologia que fortalece ainda mais o Bitcoin.
_Eles são opcodes._ Por serem opcodes, o CLTV e o CSV podem ser usados como parte de condições de resgate mais complexas. Na maioria das vezes, eles estão vinculados às condicionais que ireimos descrever no próximo capítulo.
_Eles bloqueiam as saídas._ Por serem opcodes incluídos nas transações como parte de uma ```sigPubKey```, eles apenas bloqueiam aquela saída única. Isso significa que as transações são aceitas na rede Bitcoin e que as UTXOs usadas para financiar essas transações são gastos. Não há como voltar atrás em uma transação bloqueada por tempo com o CLTV ou o CSV como acontece com um ```nLockTime``` vazio. Gastar novamente a UTXO resultante requer que as condições do timelock sejam atendidas.
Aqui está um ponto importante sobre a utilização dos timelocks: _Eles são bloqueios de mão única._ Os bloqueios de tempo são projetados para desbloquear fundos em um determinado momento. Eles não podem bloquear novamente um fundo: Uma vez que um fundo bloqueado por tempo está disponível, ele ficará disponível para ser gasto.
### Compreendendo as Possibilidades do CLTV
O _OP_CHECKLOCKTIMEVERIFY_ ou CLTV é compativel com o clássico recurso ```nLockTime```, mas no novo paradigma baseado em opcode. Ele permite que uma UTXO se torne acessível em um determinado momento ou em uma determinada altura de bloco.
O CLTV foi detalhado pela primeira vez no [BIP 65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki).
### Compreendendo as Possibilidades do CSV
O _OP_CHECKSEQUENCEVERIFY_ ou CSV depende de um novo tipo de "locktime relativo", que é definido no campo _nSequence_ da transação. Como de costume, ele pode ser definido como uma data/hora ou uma altura de bloco. Se for definido como um tempo "n", então uma transação bloqueada em um tempo relativo pode ser gasta "n x 512" segundos depois que a UTXO foi minerada, e se for definido como um bloco "n", então uma transação bloqueada em tempo relativo pode ser gasta em "n" blocos depois que a UTXO foi minerada.
O uso do ```nSequence``` para um bloqueio de tempo relativo foi detalhado primeiramente no [BIP 68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki), e o opcode CSV foi adicionado no [BIP 112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki).
## Resumo: Compreendendo As Opções de Timelock
Agora possuímos quatro opções de Timelocks:
* ```nLockTime``` para manter uma transação fora do blockchain até um dado momento específico;
* ```nSequence``` para manter uma transação fora do blockchain até um dado momento relativo;
* CLTV para tornar uma UTXO impossível de ser gasto até uma data/hora específica;
* CSV para tornar uma UTXO impossível de ser gasto até uma data/hora ou altura do bloco relativa.
## O Que Vem Depois?
Vamos continuar "Aumentando o poder do timelock com scripts do Bitcoin" na seção [§11.2: Usando CLTV em Scripts](11_2_Using_CLTV_in_Scripts.md).

View File

@ -0,0 +1,153 @@
# 11.2: Usando CLTV em Scripts
O ```OP_CHECKLOCKTIMEVERIFY``` (ou CLTV) é o complemento natural para o ```nLockTime```. Ele muda a ideia de bloquear transações por um tempo absoluto ou altura de bloco para o âmbito dos opcodes, permitindo o bloqueio das UTXOs individuais.
> :warning: **AVISO DE VERSÃO:** O CLTV ficou disponível no Bitcoin Core 0.11.2, mas deve ser amplamente implementado neste momento.
## Lembrando do nLockTime
Antes de nos aprofundarmos no CLTV, devemos primeiro lembrar do funcionamento do ```nLockTime```.
Conforme detalhado na seção [§8.1:Enviando uma transação com Locktime](08_1_Sending_a_Transaction_with_a_Locktime.md), o locktime é habilitado pela configuração de duas variáveis, o ```nLockTime``` e o ```nSequence```. O ```nSequence``` deve ser definido para ser menor do que 0xffffffff (geralmente: 0xffffffff-1), então o ```nLockTime``` será interpretado da seguinte forma:
* Se o ```nLockTime``` for inferior a 500 milhões, será interpretado como uma altura de bloco;
* Se o ```nLockTime``` for 500 milhões ou mais, será interpretado como um carimbo de data/hora UNIX.
Uma transação com ```nLockTime``` definida não pode ser gasta (ou mesmo colocada na blockchain) até que a altura do bloco ou a data/hora sejam alcançados. Neste meio tempo, a transação pode ser cancelada, ao se utilizar qualquer uma das UTXOs que constituem a transação.
## Compreendendo o Opcode CLTV
O ```OP_CHECKLOCKTIMEVERIFY``` funciona dentro do mesmo paradigma de altura de blocos ou tempos UNIX, ambos absolutos, mas é executado como parte de um Script do Bitcoin. Ele lê um argumento, que pode ser os dois já mencionados. Por meio de uma metodologia um tanto complicada, ele compara esse argumento ao tempo atual. Se for muito cedo, o script irá falhar, porém, se a condição de tempo for atendida, o script continua.
Como o CLTV é apenas parte de um script (e presumivelmente parte de uma transação P2SH), uma transação CLTV não é mantida fora da mempool como uma transação ```nLockTime```. Logo, assim que for verificado, ele vai para a blockchain e os fundos são considerados gastos. O truque é que todas as saídas que foram bloqueadas com o CLTV não estão disponíveis para _serem gastas_ até que o CLTV permita.
### Compreendendo um CLTV de Tempo Absoluto
É assim que o ```OP_CHECKLOCKTIMEVERIFY``` seria utilizado para verificar o locktime de 24 de maio de 2017:
```
1495652013 OP_CHECKLOCKTIMEVERIFY
```
Mas geralmente vamos descrever isso em uma abstração:
```
<May24> OP_CHECKLOCKTIMEVERIFY
```
Ou assim:
```
<AbsoluteTime> OP_CHECKLOCKTIMEVERIFY
```
### Compreendendo um CLTV de Altura de Bloco Absoluta
É assim que o ```OPCHECKLOCKTIMEVERIFY``` compararia a uma altura de bloqueio alcançada no dia 24 de maio de 2017:
```
467951 OP_CHECKLOCKTIMEVERIFY
```
Mas geralmente vamos abstrair assim:
```
<AbsoluteBlockHeight> OP_CHECKLOCKTIMEVERIFY
```
### Entendendo como o CLTV Realmente Funciona
A explicação acima é suficiente para usar e entender o CLTV. No entanto, o [BIP 65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki) apresenta todos os seguintes detalhes.
Um script de bloqueio só permitirá que uma transação reenvie uma UTXO bloqueado com um CLTV se o ```OP_CHECKLOCKTIMEVALUE``` verificar todas as seguintes condições:
* O campo ```nSequence``` deve ser definido como sendo menor do que 0xffffffff, geralmente 0xffffffff-1 para evitar conflitos com os timelocks relativos;
* CLTV deve retirar um operando da pilha e deve ser 0 ou maior.
* Tanto o operando da pilha quanto o ```nLockTime``` devem estar acima ou abaixo de 500 milhões, para representar o mesmo tipo de locktime absoluto;
* O valor ```nLockTime``` deve ser maior ou igual ao operando da pilha.
Portanto, a primeira coisa a se notar aqui é que o ```nLockTime``` ainda é utilizado com o CLTV. Para ser mais preciso, ele é necessário na transação que tenta _gastar novamente_ uma UTXO com o temporizador CLTV. Isso significa que não faz parte dos requisitos do script. É apenas o cronômetro que é usado para liberar os fundos, _como definido no script_.
Isso é gerenciado por meio de um entendimento inteligente de como o ```nLockTime``` funciona: Um valor para o ```nLockTime``` deve sempre ser escolhido sendo menor ou igual ao tempo presente (ou altura do bloco), de modo que a transação de gasto possa ser colocada na blockchain. Porém, devido aos requisitos do CLTV, também deve ser escolhido um valor maior ou igual ao operando do CLTV. A união desses dois conjuntos é ```NULL``` até que o tempo presente corresponda ao operando CLTV. Posteriormente, qualquer valor pode ser escolhido entre o operando do CLTV e o tempo atual. Normalmente, apenas iríamos configurar para a hora atual (ou para o bloco atual).
## Escrevendo um Script CLTV
O ```OP_CHECKLOCKTIMEVERIFY``` inclui um ```OP_VERIFY```, o que significa que ele irá parar imediatamente o script se nossa verificação não for bem-sucedida. Ele tem uma outra peculiaridade: Ao contrário da maioria dos comandos de "verificação", ele deixa o que está sendo testado na pilha (apenas no caso de querermos fazer qualquer outra verificação no tempo). Isso significa que um ```OP_CHECKLOCKTIMEVERIFY``` geralmente é seguido por um ```OP_DROP``` para limpar a pilha.
O seguinte script de bloqueio simples pode ser usado para transformar uma saída P2PKH em uma transação P2PKH bloqueada por tempo:
```
<NextYear> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
```
### Codificando um Script CLTV
Obviamente, como acontece com quaisquer scripts Bitcoin complexos, este script CLTV seria realmente codificado em um script P2SH, conforme explicado na seção [§10.1: Entendendo a Fundação do P2SH](10_1_Understanding_the_Foundation_of_P2SH.md) e na [§10.2: Construindo a Estrutura de P2SH](10_2_Building_the_Structure_of_P2SH.md).
Supondo que o ```<NextYear>``` fosse o número inteiro "1546288031" (little-endian hex: 0x9f7b2a5c) e o ```<pubKeyHash>``` fosse "371c20fb2e9899338ce5e99908e64fd30b789313", este ```redeemScript``` seria construído assim:
```
OP_PUSHDATA (4 bytes) 0x9f7b2a5c OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 OP_PUSHDATA (20 bytes) 0x371c20fb2e9899338ce5e99908e64fd30b789313 OP_EQUALVERIFY OP_CHECKSIG
```
O que se traduz em hexadecimal como sendo:
```
04 9f7b2a5c b1 75 76 a9 14 371c20fb2e9899338ce5e99908e64fd30b789313 88 ac
```
Ou se preferir:
```
$ btcc 0x9f7b2a5c OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 0x371c20fb2e9899338ce5e99908e64fd30b789313 OP_EQUALVERIFY OP_CHECKSIG
049f7b2a5cb17576a914371c20fb2e9899338ce5e99908e64fd30b78931388ac
```
O RPC ```decodescript``` pode verificar se acertamos a decodificação:
```
{
"asm": "1546288031 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 371c20fb2e9899338ce5e99908e64fd30b789313 OP_EQUALVERIFY OP_CHECKSIG",
"type": "nonstandard",
"p2sh": "2MxANZMPo1b2jGaeKTv9rwcBEiXcXYCc3x9",
"segwit": {
"asm": "0 07e55bf1eaedf43ec52af57b77ad7330506c209a70d17fa2e1853304aa8e4e5b",
"hex": "002007e55bf1eaedf43ec52af57b77ad7330506c209a70d17fa2e1853304aa8e4e5b",
"reqSigs": 1,
"type": "witness_v0_scripthash",
"addresses": [
"tb1qqlj4hu02ah6ra3f274ah0ttnxpgxcgy6wrghlghps5esf25wfedse4yw4w"
],
"p2sh-segwit": "2N4HTwMjVdm38bdaQ5h3X3VktLY74D2qBoK"
}
}
```
Não vamos mostrar continuamente como todos os Scripts do Bitcoin são codificados em transações P2SH, ao invés disso, ofereceremos estes atalhos: Quando descrevemos um script, ele será um ```redeemScript```, que normalmente seria serializado e codificado em um script de bloqueio e serializado no script de desbloqueio. Quando mostramos um procedimento de desbloqueio, será a segunda rodada de validação, seguindo a confirmação do hash do script de bloqueio.
## Gastando uma UTXO do CLTV
No caso do exemplo acima, o script de desbloqueio abaixo seria suficiente, desde que o ```nLockTime``` fosse definido em algum lugar antes da data ```<NextYear>```, e desde que o momento atual fosse, de fato, pelo menos ```<NextYear>```:
```
<signature> <pubKey>
```
### Executando um Script CLTV
Para executar o Script, primeiro devemos concatenar os scripts de desbloqueio e bloqueio:
```
Script: <signature> <pubKey> <NextYear> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Stack: [ ]
```
As três constantes seriam colocadas na pilha:
```
Script: OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Stack: [ <signature> <pubKey> <NextYear> ]
```
Então, o ```OP_CHECKLOCKTIMEVERIFY``` é executado. Ele encontra algo na pilha e verifica se o ```nSequence``` não é 0xffffffff. Finalmente, ele compara o ```<NextYear>``` com o ```nLockTime```. Se ambos são o mesmo tipo de representação e se ```nLockTime ≥ <NextYear>```, então ele é processado com sucesso (caso contrário, termina o script):
```
Script: OP_DROP OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Running: <NextYear> OP_CHECKLOCKTIMEVERIFY
Stack: [ <signature> <pubKey> <NextYear> ]
```
Então, o ```OP_DROP``` se livra daquele ```<NextYear>``` restante:
```
Script: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Running: <NextYear> OP_DROP
Stack: [ <signature> <pubKey> ]
```
Finalmente, o restante do script é executado, que é uma verificação normal de uma assinatura e chave pública.
## Resumo: Usando CLTV em Scripts
O ```OP-CHECKLOCKTIMEVERIFY``` é um opcode simples que olha para um único argumento, o interpreta como uma altura de bloco ou timestamp UNIX, e só permite que a UTXO seja desbloqueada se àquela altura de bloco ou timestamp UNIX estiver no passado. Definir o ```nLockTime``` na transação de gastos é o que permite ao Bitcoin fazer este cálculo.
> :fire: ***Qual é o poder do CLTV?*** Já vimos que os tempos de bloqueio simples eram uma das bases dos Contratos Inteligentes. O CLTV dá o próximo passo. Agora podemos garantir que uma UTXO não possa ser gasta antes de um certo tempo _e_ podemos garantir que ela também não será gasta. Em sua forma mais simples, isso poderia ser usado para criar um fundo que alguém só poderia ter acesso aos 18 anos ou um fundo de aposentadoria que só poderia ser acessado quando fizesse 50 anos. No entanto, o verdadeiro poder vem quando combinado com condicionais, onde apenas o CLTV apenas é ativado em certas situações.
## O Que Vem Depois?
Vamos continuar "Capacitando Timelock com Scripts no Bitcoin" na seção [§11.3: Usando CSV em Scripts](11_3_Using_CSV_in_Scripts.md).

View File

@ -0,0 +1,148 @@
# 11.3: Usando CSV em Scripts
O ```nLockTime``` e o ```OP_CHECKLOCKTIMEVERIFY``` (ou CLTV) são apenas um lado da equação do timelock. Do outro lado estão o ```nSequence``` e o ```OP_CHECKSEQUENCEVERIFY```, que podem ser usados para verificar tempos relativos ao invés de tempos absolutos.
> :warning: **AVISO DE VERSÃO:** O CSV está disponível no Bitcoin Core 0.12.1.
## Compreendendo o nSequence
Cada entrada em uma transação tem um valor ```nSequence``` (ou se preferirmos ```sequence```). Tem sido uma ferramenta principal para melhorias do Bitcoin, conforme discutido anteriormente na seção [§5.2: Reenviando uma transação com o RBF](05_2_Resending_a_Transaction_with_RBF.md) e na [§8.1 Enviando uma transação com Locktime](08_1_Sending_a_Transaction_with_a_Locktime.md), onde o usamos para sinalizar o RBF e o ```nLockTime```, respectivamente. No entanto, há mais um uso para o ```nSequence```, descrito no [BIP 68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Podemos usá-lo para criar um timelock relativo em uma transação.
Um timelock relativo é um bloqueio colocado em uma entrada específica de uma transação e que é calculado em relação à data de mineração da UTXO que está sendo usado na entrada. Por exemplo, se uma UTXO foi minerada no bloco #468260 e uma transação foi criada onde a entrada para aquela UTXO foi uma ```nSequence``` de 100, então a nova transação não poderia ser minerada até o bloco #468360.
Simples assim!
> :information_source: **NOTA - SEQUÊNCIA:** Este é o terceiro uso do ```nSequence``` no Bitcoin. Qualquer valor no ```nSequence``` sem o conjunto de 32 bits (1 << 31), ou seja, do 0x00000001 a 0x7ffffffff, será interpretado como um bloqueio de tempo relativo se a ```nVersion ≥ 2``` (que é o padrão do Bitcoin Core depois da versão 0.14.0). Devemos ter cuidado para garantir que os timelocks relativos não entrem em conflito com os outros dois usos de ```nSequence```, que é para sinalizar o ```nTimeLock``` e o RBF. O ```nTimeLock``` geralmente define um valor como sendo 0xffffffff-1, onde um timelock relativo não é permitido e, o RBF geralmente define um valor de "1", onde um bloqueio de tempo relativo é irrelevante, porque define um timelock de 1 bloco.
> De maneira geral, podemos lembrar do seguinte: Com um valor ```nVersion``` de 2, um valor ```nSequence``` que vai de 0x00000001 a 0x7fffffff permite um timelock relativo, o RBF e o ```nTimeLock```. Um valor ```nSequence``` de 0x7fffffff a 0xffffffff-2 permite o RBF e o ```nTimeLock```. Um valor ```nSequence``` de 0xffffffff-1 permite apenas o ```nTimeLock```. Um valor ```nSequence``` de 0xffffffff não permite nenhum dos três. Um ```nVersion``` pode ser definido como 1 para não permitir bloqueios de tempo relativos para qualquer valor do ```nSequence```. Ufa!
### Criando um CSV de Tempo de Bloco Relativo
O formato para usar o ```nSequence``` para representar bloqueios de tempo relativos é definido no [BIP 68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki) e é um pouco mais complexo do que apenas inserir um número qualquer, como fizemos no ```nTimeLock```. Ao invés disso, as especificações do BIP dividem o número de quatro bytes em três partes:
* Os primeiros dois bytes são usados para especificar um timelock relativo;
* O 23º bit é usado para sinalizar positivamente se o bloqueio se refere a um tempo ou a uma altura de bloco;
* O 32º bit é usado para sinalizar positivamente se os timelocks relativos estão desativados.
Com isso dito, a construção de um timelock relativo baseado em bloco é bem fácil, porque os dois bits sinalizados são definidos como ```0```, então apenas precisamos definir o ```nSequence``` para um valor entre 1 e 0xffff (65535). A nova transação pode ser extraída naquele número de blocos depois que o UTXO associado foi extraído.
### Criando um CSV de Tempo Relativo
Podemos definir o ```nSequence``` como um tempo relativo, onde o bloqueio dura 512 segundos vezes o valor do ```nSequence```.
A fim de fazer isso, precisamos:
1. Decidir o quanto no futuro definiremos o nosso bloqueio de tempo relativo;
2. Converter isso para segundos;
3. Dividir por 512;
4. Arredondar esse valor para cima ou para baixo e defini-lo como ```nSequence```;
5. Definir o 23º bit como verdadeiro.
Para definir um período de 6 meses no futuro, devemos primeiro calcular da seguinte forma:
```
$ seconds=$((6*30*24*60*60))
$ nvalue=$(($seconds/512))
```
Em seguida, transformar isso em hexadecimal:
```
$ hexvalue=$(printf '%x\n' $nvalue)
```
Finalmente, definimos o 23º bit do valor hexadecimal que criamos:
```
$ relativevalue=$(printf '%x\n' $((0x$hexvalue | 0x400000)))
$ echo $relativevalue
4224679
```
Se convertermos de volta, teremos o valor de 4224679 = 10000000111011010100111. O 23º dígito é definido como "1", enquanto os primeiros 2 bytes, 0111011010100111, são convertidos em 76A7 em hexadecimal ou 30375 em decimal. Multiplicando isso por 512, teremos 15,55 milhões de segundos, o que de fato é 180 dias.
## Criando uma Transação com um Timelock Relativo
Então desejamos criar uma transação simples com um timelock relativo? Tudo que precisamos fazer é emitir uma transação onde o ```nSequence``` de uma entrada é definido como mostramos acima: Com o ```nSequence``` para essa entrada definido de forma que os primeiros dois bytes definam o timelock, o 23º bit define o tipo do timelock, e o 32º bit é definido como sendo falso.
Vamos enviar a transação e veremos que ela não pode ser legalmente minerada até que blocos ou tempo suficientes tenham passado além do tempo que a UTXO foi minerada.
Exceto que praticamente ninguém faz isso. As definições do [BIP 68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki) para ```nSequence``` foram incorporadas ao Bitcoin Core ao mesmo tempo que o [BIP 112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki), que descreve o opcode CSV e o ```nSequence``` equivalente ao opcode CLTV. Assim como o CLTV, o CSV oferece recursos aprimorados. Portanto, quase todo o uso dos timelocks relativos foi com o opcode CSV, não com o valor ```nSequence``` bruto por si só.
| | Absolute Timelock | Relative Timelock |
|:--------------------:|-------------------|-------------------|
| **Transaction Bloqueada** | nTimeLock | nSequence |
| **Saída do Bloqueio** | OP_CHECKLOCKTIMEVERIFY| OP_CHECKSEQUENCEVERIFY |
## Compreendendo o Opcode CSV
O ```OP_SEQUENCEVERIFY``` nos Scripts do Bitcoin funciona quase como o ```OP_LOCKTIMEVERIFY```.
Podemos exigir que uma UTXO seja mantida por cem blocos após sua mineração:
```
100 OP_CHECKSEQUENCEVERIFY
```
Ou podemos fazer um cálculo mais complexo para exigir que uma UTXO seja retida daqui seis meses, neste caso acabaremos com um número mais complexo:
```
4224679 OP_CHECKSEQUENCEVERIFY
```
Neste caso, usaremos uma abreviatura:
```
<+6Months> OP_CHECKSEQUENCEVERIFY
```
> :warning: **ATENÇÃO:** Lembre-se de que um timelock relativo é um intervalo de tempo desde a mineração da UTXO usada como uma entrada. _Não_ é um intervalo de tempo após a criação da transação. Se usarmos uma UTXO que já foi confirmada cem vezes, e colocarmos um timelock relativo de 100 blocos nela, ela será elegível para mineração imediatamente. Os timelocks relativos têm alguns usos muito específicos, mas provavelmente não se aplicam se nosso único objetivo for determinar algum tempo definido no futuro.
### Entendendo como o CSV Realmente Funciona
O CSV tem muitas das mesmas sutilezas de uso que CLTV:
* O campo ```nVersion``` deve ser definido como 2 ou mais;
* O campo ```nSequence``` deve ser definido como sendo menor do que 0x80000000;
* Quando CSV é executado, deve haver um operando na pilha que esteja entre 0 e 0xf0000000-1;
* Tanto o operando da pilha quanto o ```nSequence``` devem ter o mesmo valor no 23º bit;
* O ```nSequence``` deve ser maior ou igual ao operando da pilha.
Assim como no CLTV, quando estiver usando uma UTXO com um CSV em condições de bloqueio, devemos definir o ```nSequence``` para habilitar a transação. Normalmente, o configuraremos com o valor exato no script de bloqueio.
## Escrevendo um Script CSV
Assim como o ```OP_CHECKLOCKTIMEVERIFY```, o ```OP_CHECKSEQUENCEVERIFY``` inclui um ```OP_VERIFY``` implícito e deixa os argumentos na pilha, exigindo um ```OP_DROP``` quando finalizar tudo.
Um script que bloquearia fundos por até seis meses após a mineração e que exigiria uma assinatura no estilo P2PKH padrão teria a seguinte aparência:
```
<+6Months> OP_CHECKSEQUENCEVERIFY OP_DROP OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
```
### Codificando um Script CSV
Ao codificar um script CSV, precisamos tomar cuidado ao codificar o valor inteiro para o timelock relativo. Deve ser passado como um número inteiro de 3 bytes, o que significa que iremos ignorar o maior byte, o que pode desativar o timelock relativo. Como é um número inteiro, precisamos nos certificar de convertê-lo para little-endian.
Isso pode ser feito com o script de shell ```integer2lehex.sh``` do capítulo anterior.
Para um tempo relativo de 100 blocos:
```
$ ./integer2lehex.sh 100
Integer: 100
LE Hex: 64
Length: 1 bytes
Hexcode: 0164
```
Embora deva ser preenchido como ```000064```, exigindo um código de ```03000064```.
Por um período relativo de 6 meses:
```
$ ./integer2lehex.sh 4224679
Integer: 4224679
LE Hex: a77640
Length: 3 bytes
Hexcode: 03a77640
```
## Gastando uma UTXO do CSV
Para gastar uma UTXO bloqueado com um script CSV, devemos definir o ```nSequence``` dessa entrada para um valor maior que o requerido no script, mas menor que o tempo entre a UTXO e o bloco atual. Isso mesmo, isso significa que precisamos saber o requisito exato no script de bloqueio. Mas temos uma cópia do ```redeemScript```, então se não conhecermos os requisitos, podemos desserializá-lo e, em seguida, definir o ```nSequence``` como sendo o número que é mostrado lá.
## Resumo: Usando CSV em Scripts
O ```nSequence``` e o CSV oferecem uma alternativa para o ```nLockTime``` e o CLTV onde bloqueamos uma transação com base em um tempo relativo desde que a entrada foi extraída, ao invés de basear o bloqueio em um tempo definido no futuro. Eles funcionam quase de forma idêntica, exceto pelo fato de que o valor do ```nSequence``` é codificado de forma ligeiramente diferente do valor do ```nLockTime```, com bits específicos significando coisas específicas.
> :fire: ***Qual é o poder do CSV?*** O CSV não é apenas uma maneira preguiçosa de bloquear uma transação, quando não queremos calcular um tempo no futuro. Ele é um paradigma totalmente diferente, um bloqueio que usaríamos se fosse importante criar uma duração mínima específica entre o momento em que uma transação é minerada e o momento em que os fundos podem ser gastos. O uso mais óbvio é (mais uma vez) para uma conta de garantia, quando desejamos um tempo preciso entre a entrada dos fundos e a saída. No entanto, ele tem possibilidades muito mais poderosas em transações fora da rede, incluindo canais de pagamento. Esses aplicativos são, por definição, construídos em transações que não são realmente colocadas na blockchain, o que significa que, se forem posteriormente colocados em um bloco, um período de tempo pode ser muito útil. Os [Hashed Timelock Contracts](https://en.bitcoin.it/wiki/Hashed_Timelock_Contracts) foram uma dessas implementações, dando a base para a rede de pagamento Lightning. Eles serão discutidos na seção [§13.3: Expandindo os Scripts do Bitcoin](13_3_Empowering_Bitcoin_with_Scripts.md).
## O Que Vem Depois?
Vamos avançar em "Programando no Bitcoin" com o [Capítulo 12: Expandindo os Scripts do Bitcoin](12_0_Expanding_Bitcoin_Scripts.md).

View File

@ -0,0 +1,20 @@
# Capítulo 12: Expandindo os Scripts do Bitcoin
Ainda há um pouco mais sobre os Scripts do Bitcoin que precisamos saber. As condicionais fornecem acesso total ao controle de fluxo, enquanto uma variedade de outros opcodes podem expandir nossas possibilidades.
## Objetivos Deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Decidir como usar os condicionais no script;
* Decidir como usar outros opcodes no script.
Os objetivos secundários do capítulo incluem a capacidade de:
* Compreender toda a gama de possibilidades de programação;
* Identificar como aprender mais sobre os opcodes.
## Tabela de Conteúdo
* [Seção 1: Usando Condicionais no Script](12_1_Using_Script_Conditionals.md)
* [Seção 2: Usando Outros Comandos no Script](12_2_Using_Other_Script_Commands.md)

View File

@ -0,0 +1,199 @@
# 12.1: Usando Condicionais no Script
Há um aspecto importante na criação de Script de Bitcoin que é crucial para expandir o seu verdadeiro poder. Os condicionais permitem que criemos vários caminhos de execução.
## Entendendo as Verificações
Já vimos um condicional dentro do script, o ```op_verify``` (0x69). Ele retira o item superior na pilha e verifica se é verdade. Se não for, _ele termina a execução do script_.
A verificação é geralmente incorporada em outros opcodes. Já vimos o ```OP_EQUALVERIFY``` (0xad), o ```OP_CHECKLOCKTIMEVERIFY``` (0xb1) e o ```OP_CHECKSEQUENCEVERIFY``` (0xb2). Cada um desses opcodes faz nossa ação central (equal, checklocktime ou checksequence) e então faz uma verificação posteriormente. Os outros opcodes de verificação que ainda não vimos são: ```OP_NUMEQUALVERIFY``` (0x9d), ```OP_CHECKSIGVERIFY``` (0xad), e ```OP_CHECKMULTISIGVERIFY``` (0xaf).
Então, como o ```OP_VERIFY``` é um condicional? É o tipo mais poderoso de condicional. Usando o ```OP_VERIFY```, _se_ uma condição é verdadeira, o script continua executando, _senão_ o script pára a execução. É assim que verificamos as condições que são absolutamente necessárias para que um script tenha sucesso. Por exemplo, o script P2PKH (```OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG```) tem duas condições necessárias: (1) a chave pública fornecida precisa corresponder ao hash da chave pública e; (2) a assinatura fornecida precisa corresponder à essa chave pública. Um ```OP_EQUALVERIFY``` é usado para a comparação do hash da chave pública e a chave pública do hash porque é uma condição absolutamente necessária. Não _queremos_ que o script continue caso isto falhe.
Podemos notar que não há ```OP_VERIFY``` no final deste script (ou da maioria dos demais), apesar da condição final também ser necessária. Isso porque o Bitcoin efetivamente faz um ```OP_VERIFY``` no final de cada script, para garantir que o resultado final da pilha seja verdadeiro. Não podemos fazer um ```OP_VERIFY``` antes do final do script, porque precisamos deixar algo na pilha para ser testado!
## Compreendendo o If/Then (Se/Então)
O outro condicional principal no script do Bitcoin é o clássico ```OP_IF``` (0x63) / ```OP_ELSE``` (0x67) / ```OP_ENDIF``` (0x68). Este é o controle típico de fluxo: se o ```OP_IF``` detectar uma afirmação verdadeira, ele executa o bloco abaixo dele, caso contrário, se houver um ```OP_ELSE```, ele o executa; e o ```OP_ENDIF``` marca o final do bloco.
> :warning: **AVISO:** Estes condicionais tecnicamente são opcodes também, mas como são pequenos números, vamos deixar o prefixo do ```OP_``` desligado para manter a brevidade e a clareza. Assim, vamos escrever ```IF```, ```ELSE```, e ```ENDIF``` ao invés de ```OP_IF```, ```OP_ELSE```, e ```OP_ENDIF```.
### Compreendendo a Ordem do If/Then
Existem duas grandes sacadas nos condicionais. Eles dificultam a leitura e determinam os scripts se não tivermos cuidado.
Primeiro, o condicional ```IF``` verifica a verdade do que é _antes dele_ (em outras palavras, o que está na pilha), e não o que está depois dele.
Segundo, o condicional ```IF``` tende a estar no script de bloqueio e o que é verificado tende a estar no script de desbloqueio.
Claro, podemos dizer, é assim que funciona o Script do Bitcoin. Condicionais usam notação polonesa reversa e adotam o paradigma padrão de desbloqueio/bloqueio, assim como todos os scripts do bitcoin. Isso é tudo verdade, mas também é o contrário da maneira padrão de ler-se condicionais IF/ELSE em outras linguagens de programação. Assim, é fácil lermos errado, inconscientemente, os condicionais do Bitcoin.
Vamos observar o seguinte código: `IF OP_DUP OP_HASH160 <pubKeyHashA> ELSE OP_DUP OP_HASH160 <pubKeyHashB> ENDIF OP_EQUALVERIFY OP_CHECKSIG`.
Olhando para os condicionais na notação do prefixo podemos ler isso da seguinte maneira:
```
IF (OP_DUP) THEN
OP_HASH160
OP_PUSHDATA <pubKeyHashA>
ELSE
OP_DUP
OP_HASH160
OP_PUSHDATA <pubKeyHashB>
ENDIF
OP_EQUALVERIFY
OP_CHECKSIG
```
Então, podemos pensar, se o ```OP_DUP``` é verdadeiro, então nós vamos fazer o primeiro bloco, senão, o segundo. Mas isso não faz sentido! Por que o ```OP_DUP``` não executaria com sucesso?!
E, de fato, não faz nenhum sentido, porque acidentalmente lemos a declaração usando a notação errada. A leitura correta é:
```
IF
OP_DUP
OP_HASH160
OP_PUSHDATA <pubKeyHashA>
ELSE
OP_DUP
OP_HASH160
OP_PUSHDATA <pubKeyHashB>
ENDIF
OP_EQUALVERIFY
OP_CHECKSIG
```
A declaração que avaliará para ```True``` ou ```False``` é colocada na pilha _antes_ de executar o ```IF```, então o bloco correto do código será executado com base naquele resultado.
Este exemplo específico de código é destinado a um simples multisig 1-de-2. O proprietário da ```<privKeyA>``` colocaria ```<signatureA> <pubKeyA> TRUE``` no script de desbloqueio, enquanto o proprietário da ```<privKeyB>``` colocaria ```<signatureB> <pubKeyB> FALSE``` no script de desbloqueio. Aquele que for rastreado como ```TRUE``` ou ```FALSE``` é o que é verificado pela instrução ```IF```/```ELSE```. Ele conta ao script qual o hash da chave pública é para verificar, então o ```OP_EQUALVERIFY``` e o ```OP_CHECKSIG``` no final fazem o verdadeiro trabalho.
### Executando um If/Then com Multisig
Com uma compreensão central dos condicionais do Bitcoin, estamos prontos para executar scripts os utilizando. Nós vamos começar criando uma ligeira variante do multisig 1-de-2 do exemplo, onde nossos usuários não precisam lembrar se eles são ```TRUE``` ou ```FALSE```. Ao invés disso, se necessário, o script verifica os hashes de chave pública, apenas exigindo um único sucesso:
```
OP_DUP OP_HASH160 <pubKeyHashA> OP_EQUAL
IF
OP_CHECKSIG
ELSE
OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG
ENDIF
```
Precisamos lembrar da notação polonesa reversa! Aquela instrução ```IF``` está se referindo ao ```OP_EQUAL``` antes dela, não ao `OP_CHECKSIG` posterior!
#### Executando a Parte Verdadeira
Veja como é executado se desbloquearmos com ```<signatureA> <pubKeyA>```:
```
Script: <signatureA> <pubKeyA> OP_DUP OP_HASH160 <pubKeyHashA> OP_EQUAL IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Stack: [ ]
```
Primeiro, colocamos as constantes na pilha:
```
Script: OP_DUP OP_HASH160 <pubKeyHashA> OP_EQUAL IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Stack: [ <signatureA> <pubKeyA> ]
```
Em seguida, nós executamos os primeiros comandos óbvios, ```OP_DUP``` e ```OP_HASH160```, e colocamos outra constante:
```
Script: OP_HASH160 <pubKeyHashA> OP_EQUAL IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Running: <pubKeyA> OP_DUP
Stack: [ <signatureA> <pubKeyA> <pubKeyA> ]
Script: <pubKeyHashA> OP_EQUAL IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Running: <pubKeyA> OP_HASH160
Stack: [ <signatureA> <pubKeyA> <pubKeyHashA> ]
Script: OP_EQUAL IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Stack: [ <signatureA> <pubKeyA> <pubKeyHashA> <pubKeyHashA> ]
```
Em seguida, executamos o ```OP_EQUAL```, que é o que vai alimentar o ```IF```:
```
Script: IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Running: <pubKeyHashA> <pubKeyHashA> OP_EQUAL
Stack: [ <signatureA> <pubKeyA> True ]
```
Agora, o ```IF``` executa, e desde que haja um ```TRUE```, ele só executa o primeiro bloco, eliminando todo o resto:
```
Script: OP_CHECKSIG
Running: True IF
Stack: [ <signatureA> <pubKeyA> ]
```
E o ```OP_CHECKSIG``` acabará sendo ```TRUE``` também:
```
Script:
Running: <signatureA> <pubKeyA> OP_CHECKSIG
Stack: [ True ]
```
#### Executando a Parte Falsa
Veja como ele iria executar se fôssemos desbloquear com ```<signatureB> <pubKeyB>```:
```
Script: <signatureB> <pubKeyB> OP_DUP OP_HASH160 <pubKeyHashA> OP_EQUAL IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Stack: [ ]
```
Primeiro, colocamos as constantes na pilha:
```
Script: OP_DUP OP_HASH160 <pubKeyHashA> OP_EQUAL IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Stack: [ <signatureB> <pubKeyB> ]
```
Em seguida, executamos os primeiros comandos óbvios, ```OP_DUP``` e ```OP_HASH160```, e adicionamos outra constante:
```
Script: OP_HASH160 <pubKeyHashA> OP_EQUAL IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Running: <pubKeyB> OP_DUP
Stack: [ <signatureB> <pubKeyB> <pubKeyB> ]
Script: <pubKeyHashA> OP_EQUAL IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Running: <pubKeyB> OP_HASH160
Stack: [ <signatureB> <pubKeyB> <pubKeyHashB> ]
Script: OP_EQUAL IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Stack: [ <signatureB> <pubKeyB> <pubKeyHashB> <pubKeyHashA> ]
```
Em seguida, executamos o ```OP_EQUAL```, que é o que vai alimentar o ```IF```:
```
Script: IF OP_CHECKSIG ELSE OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG ENDIF
Running: <pubKeyHashB> <pubKeyHashA> OP_EQUAL
Stack: [ <signatureB> <pubKeyB> False ]
```
Uhul! O resultado foi ```FALSE``` porque o ```<pubKeyHashB>``` não é igual ao ```<pubKeyHashA>```. Agora, quando o ```IF``` for executado, ele vai pular para a instrução ```ELSE```:
```
Script: OP_DUP OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG
Running: False IF
Stack: [ <signatureB> <pubKeyB> ]
```
Depois, passamos por todo o imbróglio, começando com outro ```OP_DUP```, mas eventualmente o testando usando outro ```pubKeyHash```:
```
Script: OP_HASH160 <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG
Running: <pubKeyB> OP_DUP
Stack: [ <signatureB> <pubKeyB> <pubKeyB> ]
Script: <pubKeyHashB> OP_EQUALVERIFY OP_CHECKSIG
Running: <pubKeyB> OP_HASH160
Stack: [ <signatureB> <pubKeyB> <pubKeyHashB> ]
Script: OP_EQUALVERIFY OP_CHECKSIG
Stack: [ <signatureB> <pubKeyB> <pubKeyHashB> <pubKeyHashB> ]
Script:OP_CHECKSIG
Running: <pubKeyHashB> <pubKeyHashB> OP_EQUALVERIFY
Stack: [ <signatureB> <pubKeyB> ]
Script:
Running: <signatureB> <pubKeyB> OP_CHECKSIG
Stack: [ True ]
```
Isso provavelmente não é tão eficiente quanto um verdadeiro multisig do Bitcoin, mas é um bom exemplo de como os resultados adicionados à pilha devido a testes anteriores podem ser usados para alimentar condicionais futuros. Neste caso, é o fracasso da primeira assinatura que diz ao condicional que deve ir verificar a segunda.
## Entendendo os Demais Condicionais
Existem alguns outros condicionais para ser analisados. O maior deles é o ```OP_NOTIF``` (0x64), que é o oposto de ```OP_IF```. Ele executa o próximo bloco se o item superior for ```FALSE```. Um ```ELSE``` pode ser colocado junto, que como usual é executado se o primeiro bloco não for executado. Podemos ainda terminar com o ```OP_ENDIF```.
Há também um ```OP_IFDUP``` (0x73), que duplica o item de pilha superior somente se o resultado não for 0.
Essas opções são usadas com muito menos frequência do que a construção usando ```IF```/```ELSE```/```ENDIF```.
## Resumo: Usando Condicionais no Script
Os condicionais no script do Bitcoin permitem parar o script (usando o ```OP_VERIFY```) ou escolher diferentes ramos de execução (usando ```OP_IF```). No entanto, ler o ```OP_IF``` pode ser um pouco complicado. Precisamos lembrar de que é o item adicionado à pilha _antes_ do operador ```OP_IF``` ser executado que controla a sua execução. Esse item normalmente fará parte do script de desbloqueio (ou será um resultado direto de itens do script de desbloqueio).
> :fire: ***Qual é o poder dos condicionais?*** Os condicionais do script são o principal bloco de construção no Bitcoin Script. Eles transformam os scripts simples e estáticos do Bitcoin em scripts de Bitcoin complexos e dinâmicos que podem avaliar de maneira diferente com base em diferentes momentos, diferentes circunstâncias ou diferentes entradas de usuário. Em outras palavras, eles são o último pilar dos contratos inteligentes.
## O Que Vem Depois?
Vamos continuar "Expandindo os Scripts do Bitcoin" na seção [§12.2: Usando Outros Comandos no Script](12_2_using_other_script_commands.md).

View File

@ -0,0 +1,85 @@
# 12.2: Usando Outros Comandos no Script
Provavelmente já temos em mãos a maioria dos opcodes do Bitcoin Script que iremos usar na maioria dos nossos scripts. No entanto, o Bitcoin Script oferece muito mais opções, o que pode vir a ser exatamente o que precisamos para criar o instrumento financeiro dos nossos sonhos.
Devemos consultar a [página do script do Bitcoin](https://en.bitcoin.it/wiki/script) para termos uma lista mais completa de todos esses e muitos outros comandos. Esta seção destaca apenas os opcodes mais notáveis.
## Entendendo os Opcodes Aritméticos
Os opcodes aritméticos manipulam ou testam números.
Manipulam um número:
* OP_1ADD (0x8b) - Adiciona uma unidade;
* OP_1SUB (0x8C) - Subtrai uma unidade;
* OP_NEGATE (0x8f) - Inverte o sinal do número;
* OP_ABS (0x90) - Torna o número positivo;
* OP_NOT (0x91) - Troca 1 por 0, senão 0.
Veja também: ```OP_0NOTEQUAL``` (0x92).
Manipulam dois números matematicamente:
* OP_ADD (0x93) - Adiciona dois números;
* OP_SUB (0x94) - Subtrai dois números;
* OP_MIN (0xA3) - Retorna o menor entre dois números;
* OP_MAX (0xA4) - Retorna o maior entre dois números.
Manipulam dois números logicamente:
* OP_BOOLAND (0x9a) - 1 se ambos os números não são 0, senão 0;
* OP_BOOLOR (0x9B) - 1 se qualquer número não é 0, senão 0.
Testa dois números:
* OP_NUMEQUAL (0x9C) - 1 se ambos os números forem iguais, senão 0;
* OP_LESSTHAN (0x9f) - 1 se o primeiro número for menor que o segundo, senão 0;
* OP_GREATERTHAN (0xA0) - 1 se o primeiro número for maior que o segundo, senão 0;
* OP_LESSTHANOREQUAL (0xA1) - 1 se o primeiro número for menor ou igual ao segundo, senão 0;
* OP_GREATERTHANOREQUAL (0xA2) - 1 se o primeiro número for maior ou igual a segundo, senão 0.
Veja também: ```OP_NUMEQUALVERIFY``` (0x9d) e ```OP_NUMNOTEQUAL``` (0x9e)
Testa três números:
* OP_WITHIN (0xA5) - 1 se um número estiver no intervalo de dois outros números.
## Compreendendo os Opcodes de Pilha
Há um número chocante de opcodes de pilha, mas além de ```OP_DROP```, ```OP_DUP```, e às vezes ```OP_SWAP```, eles geralmente não serão necessários se tivermos cuidado com a ordem da pilha. No entanto, aqui estão alguns dos mais interessantes:
* OP_DEPTH (0x74) - Aumenta o tamanho da pilha;
* OP_DROP (0x75) - Retira o item superior da pilha;
* OP_DUP (0x76) - Duplica o item superior da pilha;
* OP_PICK (0x79) - Duplica o enésimo item da pilha começando pelo topo;
* OP_ROLL (0x7a) - Move o enésimo item para o topo da pilha;
* OP_SWAP(0x7C) - Troca os dois principais itens da pilha.
Veja também: `OP_TOALTSTACK` (0x6b), `OP_FROMALTSTACK` (0x6c), `OP_2DROP` (0x6d), `OP_2DUP` (0x6e), `OP_3DUP` (0x6f), `OP_2OVER` (0x70), `OP_2ROT` (0x71), `OP_2SWAP` (0x72), `OP_IFDUP` (0x73), `OP_NIP` (0x77), `OP_OVER` (0x78), `OP_ROT` (0x7b), e `OP_TUCK` (0x7d).
## Compreendendo os Opcodes Criptográficos
Finalmente, uma variedade de opcodes para dar suporte ao hashing e à verificação de assinatura:
Hash:
* OP_RIPEMD160 (0xa6) — RIPEMD-160;
* OP_SHA1 (0xa7) — SHA-1;
* OP_SHA256 (0xa8) - SHA-256;
* OP_HASH160 (0xa9) — SHA-256 + RIPEMD-160;
* OP_HASH256 (0xaa) — SHA-256 + SHA-256.
Verifica as assinaturas:
* OP_CHECKSIG (0xac) - Verifica uma assinatura;
* OP_CHECKMULTISIG (0xae) - Verifica um multisig m-de-n.
Veja também: `OP_CODESEPARATOR` (0xab), `OP_CHECKSIGVERIFY` (0xad), e `OP_CHECKMULTISIGVERIFY` (0xaf).
## Resumo: Usando Outros Comandos no Script
O Bitcoin Script inclui uma ampla gama de opcodes aritméticos, de pilha e criptográficos. A maioria desses opcodes adicionais provavelmente não serão tão comuns quanto os discutidos nas seções anteriores, mas, no entanto, estão disponíveis caso precisemos utilizá-los para escrever nosso script!
## O Que Vem Depois?
Vamos avançar "Expandindo os Scripts do Bitcoin" com o [Capítulo 13: Projetando Scripts Reais no Bitcoin](13_0_Designing_real_bitcoin_scripts.md).

View File

@ -0,0 +1,22 @@
# Capítulo 13: Projetando Scripts Reais no Bitcoin
Até então, nossos scripts no Bitcoin têm sido exemplos teóricos, porque ainda estamos montando as peças do quebra-cabeça. Agora, com o repertório completo do Bitcoin Script em mãos, estamos prontos para nos aprofundarmos em vários scripts do mundo real e ver como eles funcionam.
## Objetivos Deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Avaliar scripts do Bitcoin do mundo real;
* Criar scripts do Bitcoin no mundo real.
Os objetivos secundários incluem a capacidade de:
* Entender os scripts do Bitcoin existentes;
* Compreender a importância das assinaturas.
## Tabela de Conteúdo
* [Seção 1: Escrevendo Scripts de Quebra-Cabeças](13_1_Writing_Puzzle_Scripts.md)
* [Seção 2: Escrevendo Scripts Complexos de Multisig](13_2_Writing_Complex_Multisig_Scripts.md)
* [Seção 3: Capacitando o Bitcoin com Scripts](13_3_Empowering_Bitcoin_with_Scripts.md)

View File

@ -0,0 +1,509 @@
# 13.1: Escrevendo Scripts de Quebra-Cabeças
Os scripts de Bitcoin realmente _não_ precisam depender do conhecimento de uma chave secreta. Ao invés disso, eles podem ser quebra-cabeças de qualquer tipo.
## Escrevendo Scripts de Álgebra Simples
Nosso primeiro script real, da seção [§9.2: Executando um Script no Bitcoin](09_2_Running_a_Bitcoin_Script.md) foi um quebra-cabeça simples. Esse script Bitcoin, ```OP_ADD 99 OP_EQUAL```, poderia ter sido descrito da seguinte forma: ```x + y = 99```.
Esse tipo de script não tem muita aplicabilidade no mundo real, pois é muito fácil reivindicar os fundos. Mas, um quebra-cabeça que distribui pequenos valores em Bitcoin pode ser um entretenimento divertido.
Mais notavelmente, a criação de quebra-cabeças algébricos fornece uma boa compreensão de como funcionam as funções aritméticas no Bitcoin Script.
### Escrevendo um Script Multiplicador
O Bitcoin Script possui vários opcodes que foram desativados para manter a segurança do sistema. Um deles é o ```OP_MUL```, que teria permitido a multiplicação, mas, está desabilitado.
Então, como escreveríamos uma função algébrica como ```3x + 7 = 13```?
A resposta mais óbvia é usando o ```OP_DUP``` no número inserido no script de bloqueio duas vezes. Então podemos colocar o ```7``` e continuar adicionando até obter o total. O script de bloqueio completo ficaria assim: ```OP_DUP OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL```.
Veja como seria executado o script de desbloqueio correto do ```2```:
```
Script: 2 OP_DUP OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
Stack: [ ]
Script: OP_DUP OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
Stack: [ 2 ]
Script: OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
Running: 2 OP_DUP
Stack: [ 2 2 ]
Script: 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
Running: 2 OP_DUP
Stack: [ 2 2 2 ]
Script: OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
Stack: [ 2 2 2 7 ]
Script: OP_ADD OP_ADD 13 OP_EQUAL
Running: 2 7 OP_ADD
Stack: [ 2 2 9 ]
Script: OP_ADD 13 OP_EQUAL
Running: 2 9 OP_ADD
Stack: [ 2 11 ]
Script: 13 OP_EQUAL
Running: 2 11 OP_ADD
Stack: [ 13 ]
Script: OP_EQUAL
Stack: [ 13 13 ]
Script:
Running: 13 13 OP_EQUAL
Stack: [ True ]
```
Ou se você preferir usar o `btcdeb`:
```
$ btcdeb '[2 OP_DUP OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL]'
btcdeb 0.2.19 -- type `btcdeb -h` for start up options
valid script
9 op script loaded. type `help` for usage information
script | stack
---------+--------
2 |
OP_DUP |
OP_DUP |
7 |
OP_ADD |
OP_ADD |
OP_ADD |
13 |
OP_EQUAL |
#0000 2
btcdeb> step
<> PUSH stack 02
script | stack
---------+--------
OP_DUP | 02
OP_DUP |
7 |
OP_ADD |
OP_ADD |
OP_ADD |
13 |
OP_EQUAL |
#0001 OP_DUP
btcdeb> step
<> PUSH stack 02
script | stack
---------+--------
OP_DUP | 02
7 | 02
OP_ADD |
OP_ADD |
OP_ADD |
13 |
OP_EQUAL |
#0002 OP_DUP
btcdeb> step
<> PUSH stack 02
script | stack
---------+--------
7 | 02
OP_ADD | 02
OP_ADD | 02
OP_ADD |
13 |
OP_EQUAL |
#0003 7
btcdeb> step
<> PUSH stack 07
script | stack
---------+--------
OP_ADD | 07
OP_ADD | 02
OP_ADD | 02
13 | 02
OP_EQUAL |
#0004 OP_ADD
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 09
script | stack
---------+--------
OP_ADD | 09
OP_ADD | 02
13 | 02
OP_EQUAL |
#0005 OP_ADD
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 0b
script | stack
---------+--------
OP_ADD | 0b
13 | 02
OP_EQUAL |
#0006 OP_ADD
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 0d
script | stack
---------+--------
13 | 0d
OP_EQUAL |
#0007 13
btcdeb> step
<> PUSH stack 0d
script | stack
---------+--------
OP_EQUAL | 0d
| 0d
#0008 OP_EQUAL
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 01
script | stack
---------+--------
| 01
```
### Escrevendo um Sistema de Equações
E se quiséssemos escrever um sistema de equações, como ```x + y = 3```,```y + z = 5``` e ```x + z = 4```? A álgebra diz que as respostas resultariam em ```x = 1```,```y = 2``` e ```z = 3```. Mas, como programamos isso?
Obviamente, depois que o remetente inserir os três números, precisaremos de duas cópias de cada número, uma vez que cada número entra em duas equações diferentes. O ```OP_3DUP``` cuida disso e resulta em```x y z x y z``` estando na pilha. Tirar dois itens de cada vez resultará em ```y z```,```z x``` e ```x y```. Pronto! Essas são as três equações, então só precisamos adicioná-las e testá-las na ordem correta! Aqui está o script completo: ```OP_3DUP OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL```.
Veja como funciona com o script de desbloqueio correto de ```1 2 3```:
```
Script: 1 2 3 OP_3DUP OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Stack: [ ]
Script: OP_3DUP OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Stack: [ 1 2 3 ]
Script: OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Running: 1 2 3 OP_3DUP
Stack: [ 1 2 3 1 2 3 ]
Script: 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Running: 2 3 OP_ADD
Stack: [ 1 2 3 1 5 ]
Script: OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Stack: [ 1 2 3 1 5 5 ]
Script: OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Running: 5 5 OP_EQUALVERIFY
Stack: [ 1 2 3 1 ] — Does Not Exit
Script: 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Running: 3 1 OP_ADD
Stack: [ 1 2 4 ]
Script: OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
Stack: [ 1 2 4 4 ]
Script: OP_ADD 3 OP_EQUAL
Running: 4 4 OP_EQUALVERIFY
Stack: [ 1 2 ] — Does Not Exit
Script: 3 OP_EQUAL
Running: 1 2 OP_ADD
Stack: [ 3 ]
Script: OP_EQUAL
Stack: [ 3 3 ]
Script:
Running: 3 3 OP_EQUAL
Stack: [ True ]
```
Aqui está usando o `btcdeb`:
```
$ btcdeb '[1 2 3 OP_3DUP OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL]'
btcdeb 0.2.19 -- type `btcdeb -h` for start up options
valid script
13 op script loaded. type `help` for usage information
script | stack
---------------+--------
1 |
2 |
3 |
OP_3DUP |
OP_ADD |
5 |
OP_EQUALVERIFY |
OP_ADD |
4 |
OP_EQUALVERIFY |
OP_ADD |
3 |
OP_EQUAL |
#0000 1
btcdeb> step
<> PUSH stack 01
script | stack
---------------+--------
2 | 01
3 |
OP_3DUP |
OP_ADD |
5 |
OP_EQUALVERIFY |
OP_ADD |
4 |
OP_EQUALVERIFY |
OP_ADD |
3 |
OP_EQUAL |
#0001 2
btcdeb> step
<> PUSH stack 02
script | stack
---------------+--------
3 | 02
OP_3DUP | 01
OP_ADD |
5 |
OP_EQUALVERIFY |
OP_ADD |
4 |
OP_EQUALVERIFY |
OP_ADD |
3 |
OP_EQUAL |
#0002 3
btcdeb> step
<> PUSH stack 03
script | stack
---------------+--------
OP_3DUP | 03
OP_ADD | 02
5 | 01
OP_EQUALVERIFY |
OP_ADD |
4 |
OP_EQUALVERIFY |
OP_ADD |
3 |
OP_EQUAL |
#0003 OP_3DUP
btcdeb> step
<> PUSH stack 01
<> PUSH stack 02
<> PUSH stack 03
script | stack
---------------+--------
OP_ADD | 03
5 | 02
OP_EQUALVERIFY | 01
OP_ADD | 03
4 | 02
OP_EQUALVERIFY | 01
OP_ADD |
3 |
OP_EQUAL |
#0004 OP_ADD
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 05
script | stack
---------------+--------
5 | 05
OP_EQUALVERIFY | 01
OP_ADD | 03
4 | 02
OP_EQUALVERIFY | 01
OP_ADD |
3 |
OP_EQUAL |
#0005 5
btcdeb> step
<> PUSH stack 05
script | stack
---------------+--------
OP_EQUALVERIFY | 05
OP_ADD | 05
4 | 01
OP_EQUALVERIFY | 03
OP_ADD | 02
3 | 01
OP_EQUAL |
#0006 OP_EQUALVERIFY
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 01
<> POP stack
script | stack
---------------+--------
OP_ADD | 01
4 | 03
OP_EQUALVERIFY | 02
OP_ADD | 01
3 |
OP_EQUAL |
#0007 OP_ADD
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 04
script | stack
---------------+--------
4 | 04
OP_EQUALVERIFY | 02
OP_ADD | 01
3 |
OP_EQUAL |
#0008 4
btcdeb> step
<> PUSH stack 04
script | stack
---------------+--------
OP_EQUALVERIFY | 04
OP_ADD | 04
3 | 02
OP_EQUAL | 01
#0009 OP_EQUALVERIFY
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 01
<> POP stack
script | stack
---------------+--------
OP_ADD | 02
3 | 01
OP_EQUAL |
#0010 OP_ADD
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 03
script | stack
---------------+--------
3 | 03
OP_EQUAL |
#0011 3
btcdeb> step
<> PUSH stack 03
script | stack
---------------+--------
OP_EQUAL | 03
| 03
#0012 OP_EQUAL
btcdeb> step
<> POP stack
<> POP stack
<> PUSH stack 01
script | stack
---------------+--------
| 01
```
> :warning: **ATENÇÃO** O ```btcdeb``` não é útil apenas para fornecer a visualização desses scripts, mas também para verificar os resultados. Com certeza, erramos na primeira vez, testando as equações na ordem errada. É tão fácil cometer um erro financeiramente fatal em um script do Bitcoin, e é por isso que todo script deve ser testado exaustivamente.
## Escrevendo Scripts Computacionais Simples
Embora os scripts de quebra-cabeça sejam triviais, podem realmente ter utilidade no mundo real se quisermos terceirizar uma computação. Podemos simplesmente criar um script que requer a resposta do cálculo e enviar fundos para o endereço P2SH como recompensa. Assim, a recompensa ficará lá até que alguém dê a resposta.
Por exemplo, Peter Todd [ofereceu recompensas](https://bitcointalk.org/index.php?topic=293382.0) para resolver equações que demonstram colisões para algoritmos criptográficos padrão. Aqui estava o script para confirmar uma colisão SHA1: ```OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL```. Requer duas entradas, que serão os dois números que colidem.
Veja como funciona com as respostas corretas.
Primeiro, preenchemos nossa pilha:
```
Script: <numA> <numB> OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Stack: [ ]
Script: OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Stack: [ <numA> <numB> ]
Script: OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Running: <numA> <numB> OP_2DUP
Stack: [ <numA> <numB> <numA> <numB> ]
```
Em seguida, nos certificamos de que os dois números não são iguais, saindo se forem:
```
Script: OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Running: <numA> <numB> OP_EQUAL
Stack: [ <numA> <numB> False ]
Script: OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Running: False OP_NOT
Stack: [ <numA> <numB> True ]
Script: OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
Running: True OP_VERIFY
Stack: [ <numA> <numB> ] — Does Not Exit
```
Agora criamos dois SHAs:
```
Script: OP_SWAP OP_SHA1 OP_EQUAL
Running: <numB> OP_SHA1
Stack: [ <numA> <hashB> ]
Script: OP_SHA1 OP_EQUAL
Running: <numA> <hashB> OP_SWAP
Stack: [ <hashB> <numA> ]
Script: OP_EQUAL
Running: <numA> OP_SHA1
Stack: [ <hashB> <hashA> ]
```
Finalmente, vemos se eles combinam.
```
Script:
Running: <hashB> <hashA> OP_EQUAL
Stack: [ True ]
```
Este é um bom script porque mostra o uso cuidadoso da lógica (com o ```OP_NOT``` e o ```OP_VERIFY```) e bom uso das funções de pilha (com o ```OP_SWAP```). Trata-se de um ótimo exemplo de uma função do mundo real. E isso é muito real. Quando o [SHA-1 foi quebrado](https://shattered.io/), 2,48 BTC foram rapidamente liberados do endereço, com um valor total de cerca de $3.000 na época.
O ```btcdeb``` pode ser executado para provar a colisão (e o script):
```
btcdeb $ btcdeb '[255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017f46dc93a6b67e013b029aaa1db2560b45ca67d688c7f84b8c4c791fe02b3df614f86db1690901c56b45c1530afedfb76038e972722fe7ad728f0e4904e046c230570fe9d41398abe12ef5bc942be33542a4802d98b5d70f2a332ec37fac3514e74ddc0f2cc1a874cd0c78305a21566461309789606bd0bf3f98cda8044629a1 255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017346dc9166b67e118f029ab621b2560ff9ca67cca8c7f85ba84c79030c2b3de218f86db3a90901d5df45c14f26fedfb3dc38e96ac22fe7bd728f0e45bce046d23c570feb141398bb552ef5a0a82be331fea48037b8b5d71f0e332edf93ac3500eb4ddc0decc1a864790c782c76215660dd309791d06bd0af3f98cda4bc4629b1 OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL']
```
As outras [recompensas](https://bitcointalk.org/index.php?topic=293382.0) de Peter Todd permanecem intocadas, pelo menos até o momento da redação deste artigo. Elas são todas escritas da mesma maneira que o exemplo SHA-1 acima.
## Compreendendo as Limitações dos Scripts de Quebra-Cabeça
Os scripts de quebra-cabeça são ótimos para examinar mais detalhadamente a programação no Bitcoin, mas só os veremos em uso no mundo real se estiverem mantendo pequenas quantias de fundos ou se forem destinados ao resgate por usuários muito habilidosos. Há uma razão para isso: eles não são seguros.
É aqui que a segurança cai:
Primeiro, qualquer um pode resgatá-los sem saber muito sobre um segredo. Eles precisam ter o ```redeemScript```, sim, que oferece alguma proteção, mas uma vez que consigam, esse é provavelmente o único segredo necessário, a menos que nosso quebra-cabeça seja _realmente_ difícil, como um quebra-cabeça computacional.
Em segundo lugar, o resgate real não é seguro. Normalmente, uma transação de Bitcoin é protegida pela assinatura. Como a assinatura cobre a transação, ninguém na rede pode reescrever essa transação para enviar para o endereço sem invalidar a assinatura (e, portanto, a transação). Isso não é verdade com transações cujas entradas são apenas números. Qualquer um poderia pegar a transação e reescrevê-la para permitir o roubo dos fundos. Se eles conseguirem colocar a transação em um bloco antes da nossa transação, eles ganham e nós não receberemos o dinheiro do quebra-cabeça. Existem soluções para isso, mas elas envolvem a mineração do bloco por conta própria ou um pool confiável para minerá-lo, e nenhuma dessas opções é racional para um usuário comum do Bitcoin.
Ainda assim, as recompensas criptográficas de Peter Todd provam que os scripts de quebra-cabeça têm sim alguma aplicação no mundo real.
## Resumo: Escrevendo Quebra-Cabeças com Scripts
Os scripts de quebra-cabeça são uma ótima introdução aos scripts do Bitcoin mais realistas e complexos. Eles demonstram o poder das funções matemáticas e de pilha no Bitcoin Script e como podem ser cuidadosamente combinadas para criar perguntas que requerem respostas muito específicas. No entanto, o uso no mundo real também é limitado pelos problemas de segurança inerentes às transações no Bitcoin não assinadas.
> :fire: ***Qual é o poder do script de quebra-cabeça?*** Apesar das limitações, os scripts de quebra-cabeça têm sido usados no mundo real como prêmios para recompensas computacionais. Qualquer pessoa que consiga descobrir um quebra-cabeça complexo, cuja solução provavelmente tenha algum impacto no mundo real, pode ganhar a recompensa. Se vão conseguir sacar para seus endereços, é outra questão.
## O Que Vem Depois?
Vamos continuar "Projetando Scripts Reais no Bitcoin" na seção [§13.2: Escrevendo Scripts Complexos de Multisig](13_2_Writing_Complex_Multisig_Scripts.md).

View File

@ -0,0 +1,151 @@
# 13.2: Escrevendo Scripts Complexos de Multisig
Até o momento, os multisigs descritos nesses documentos têm sido inteiramente simples, na forma m-de-n ou n-de-n. No entanto, podemos desejar multisigs mais complexos, onde as pessoas que assinam as transações variam ou onde diferentes opções podem se tornar disponíveis ao longo do tempo.
## Escrevendo um Multisig Variável
Um multisig variável requer diferentes números de pessoas para assinar, dependendo de quem está assinando.
### Escrevendo um Multisig com um Único Assinante ou Cossignatários
Imagine uma empresa em que o presidente ou dois em cada três vice-presidentes concordem com o uso dos fundos.
Podemos escrever isso criando uma instrução ```IF```/```ELSE```/```ENDIF``` que tem dois blocos, um para o presidente e sua assinatura um-de-um e um para os vice-presidentes e suas assinaturas dois-de-três. Podemos então determinar qual bloco usar com base em quantas assinaturas estão no script de desbloqueio. Se usarmos ```OP_DEPTH 1 OP_EQUAL``` estaremos dizendo que há um item na pilha, e iremos partir daí.
O script de bloqueio completo seria ```OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF```.
Se executado pelo presidente, seria assim:
```
Script: <sigPres> OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
Stack: [ ]
Script: OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
Stack: [ <sigPres> ]
Script: 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
Running: <SigPres> OP_DEPTH
Stack: [ <sigPres> 1 ]
Script: OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
Stack: [ <sigPres> 1 1 ]
Script: IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
Running: 1 1 OP_EQUAL
Stack: [ <sigPres> True ]
```
Como o resultado é `True`, o script agora se reduz para a instrução ```IF```:
```
Script: <pubKeyPres> OP_CHECKSIGNATURE
Running: True IF
Stack: [ <sigPres> ]
Script: OP_CHECKSIGNATURE
Stack: [ <sigPres> <pubKeyPres> ]
Script:
Running: <sigPres> <pubKeyPres> OP_CHECKSIGNATURE
Stack: [ True ]
```
Se administrado por dois vice-presidentes, ficaria assim:
```
Script: 0 <sigVPA> <sigVPB> OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
Stack: [ ]
Script: OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
Stack: [ 0 <sigVPA> <sigVPB> ]
Script: 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
Running: 0 <sigVPA> <sigVPB> OP_DEPTH
Stack: [ 0 <sigVPA> <sigVPB> 3 ]
Script: OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
Stack: [ 0 <sigVPA> <sigVPB> 3 1 ]
Script: IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
Running: 3 1 OP_EQUAL
Stack: [ 0 <sigVPA> <sigVPB> False ]
```
Como o resultado é `False`, o script agora se reduz à instrução ```ELSE```:
```
Script: 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG
Running: False IF
Stack: [ 0 <sigVPA> <sigVPB> ]
Script: OP_CHECKMULTISIG
Stack: [ 0 <sigVPA> <sigVPB> 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 ]
Script:
Running: 0 <sigVPA> <sigVPB> 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG
Stack: [ ]
```
Podemos notar que a assinatura do presidente usa apenas um simples ```OP_CHECKSIGNATURE``` ao invés do código mais complexo normalmente exigido para um P2PKH. Podemos nos safar em incluir a chave pública no script de bloqueio, evitando um trabalhão padrão, porque é um hash e não será revelado (por meio do ```redeemScript```) até que a transação seja desbloqueada. Isso também permite que todos os possíveis assinantes assinem usando a mesma metodologia.
O único problema é se o presidente estiver distraído e acidentalmente assinar uma transação com um dos vice-presidentes, porque ele se lembra de ser um multisig 2-de-3. Uma opção é decidir que essa é uma condição de falha aceitável, porque o presidente está usando o multisig incorretamente. Outra opção é transformar o multisig 2-de-3 em um multisig 2-de-4, caso o presidente não tolere falhas: ```OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> < pubKeyVPC> <pubKeyPres> 4 OP_CHECKMULTISIG ENDIF```. Isso permitiria ao presidente assinar por engano com qualquer vice-presidente, mas não afetaria as coisas se dois vice-presidentes quisessem assinar (corretamente).
### Escrevendo um Multisig com um Assinante Obrigatório
Outra possibilidade de multisig envolve ter um multisig m-de-n onde um dos assinantes é necessário. Isso geralmente pode ser gerenciado dividindo o multisig em vários m de n-1 multisigs. Por exemplo, um multisig 2 de 3 em que um dos signatários é necessário seria, na verdade, dois multisigs 2-de-2, cada um incluindo o signatário necessário.
Aqui está uma maneira simples de criar um script para isso:
```
OP_3DUP
2 <pubKeyRequired> <pubKeyA> 2 OP_CHECKMULTISIG
NOTIF
2 <pubKeyRequired> <pubKeyB> 2 OP_CHECKMULTISIG
ENDIF
```
O script de desbloqueio seria ```0 <pubKeyRequired> <pubKeyA>``` ou ```0 <pubKeyRequired> <pubKeyB>```.
Primeiro, o script verifica as assinaturas no ```<pubKeyRequired> <pubKeyA>```. Se falhar, será verificado no ```<pubKeyRequired> <pubKeyB>```.
O resultado do ```OP_CHECKMULTISIG``` final que foi executado será deixado no topo da pilha (embora haja um resto abaixo dele se o primeiro for bem-sucedido).
## Escrevendo um Multisig de Garantia
Falamos muito sobre garantia. Os multisigs complexos combinados com timelocks oferecem uma maneira automatizada de criá-las de maneira robusta.
Imagine a compradora de imóveis Alice e o vendedor de imóveis Bob que estão trabalhando com um agente de garantia. A maneira fácil de fazer o script seria como um multisig onde qualquer uma das três partes poderia liberar o dinheiro: ou o vendedor e o comprador concordam ou o agente de garantia assume o controle e concorda com uma das partes: ```2 <pubKeyA> <pubKeyB> <pubKeyEscrow> 3 OP_CHECKMULTISG```.
No entanto, isso enfraquece o poder do agente de garantia e permite que o vendedor e o comprador acidentalmente tomem uma decisão errada entre eles. O que é uma das coisas que um sistema de garantia deve evitar. Portanto, pode ser que o que realmente desejamos seja o sistema que acabamos de criar, onde o agente de custódia é uma parte necessária no multisig 2 de 3: ```OP_3DUP 2 <pubKeyEscrow> <pubKeyA> 2 OP_CHECKMULTISIG NOTIF 2 <pubKeyEscrow > <pubKeyB> 2 OP_CHECKMULTISIG ENDIF```.
No entanto, isso não nos reguarda contra imprevistos. Se o agente de custódia morre ou foge para as Bahamas durante o processo, o comprador e o vendedor ficam sem o dinheiro. É aqui que entra o timelock. Podemos criar um teste adicional que só será executado se tivermos passado o final do nosso período de garantia. Nessa situação, permitimos que o comprador e o vendedor assinem juntos:
```
OP_3DUP
2 <pubKeyEscrow> <pubKeyA> 2 OP_CHECKMULTISIG
NOTIF
OP_3DUP
2 <pubKeyEscrow> <pubKeyB> 2 OP_CHECKMULTISIG
NOTIF
<+30Days> OP_CHECKSEQUENCEVERIFY OP_DROP
2 <pubKeyA> <pubKeyB> 2 OP_CHECKMULTISIG
ENDIF
ENDIF
```
Primeiro, testamos uma assinatura para o comprador e o agente de garantia e, em seguida, uma assinatura para o vendedor e o agente de garantia. Se ambos falharem e 30 dias se passaram, também permitimos uma assinatura para o comprador e o vendedor.
### Escrevendo um Multisig de Garantia Centrado no Comprador
O [BIP 112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki#Escrow_with_Timeout) oferece um exemplo diferente deste tipo de garantia que não tem proteções extras para evitar a não-participação do agente de garantia, mas que dá à Alice controle total se a garantia falhar.
```
IF
2 <pubKeyA> <pubKeyB> <pubKeyEscrow> 3 OP_CHECKMULTISIG
ELSE
<+30Days> OP_CHECKSEQUENCEVERIFY OP_DROP
<pubKeyA> OP_CHECKSIGNATURE
ENDIF
```
Aqui, qualquer um dos três assinantes pode liberar o dinheiro a qualquer momento, mas depois de 30 dias, Alice pode recuperar o dinheiro por conta própria.
Observe que este script requer que um ```True``` ou ```False``` seja passado para identificar qual caminho será utilizado. Esta é uma maneira mais simples e menos intensiva computacionalmente de oferecer suporte a ramificações no Bitcoin Script. É algo bem comum.
No início, o seguinte ```sigScript``` seria permitido: ```0 <signer1> <signer2> True```. Após 30 dias, Alice poderia produzir um ```sigScript``` como este: ```<sigA> False```.
## Resumo: Escrevendo Scripts Complexos de Multisig
Os multisigs mais complexos podem ser normalmente criados combinando assinaturas ou multi-assinaturas com condicionais e testes. Os multisigs resultantes podem ser variáveis, exigindo diferentes números de assinantes com base em quem são e quando estão assinando.
> :fire: ***Qual é o poder dos scripts complexos de multisigs?*** Mais do que qualquer outra coisa que vimos até agora, os scripts complexos de multisig são contratos realmente inteligentes. Eles podem ser muito precisos sobre quem tem permissão para assinar e quando. Empresas com vários níveis, parcerias e garantias podem utilizar soluções semelhantes. O uso de outros recursos poderosos como os timelocks pode proteger ainda mais esses fundos, permitindo que sejam liberados ou mesmo devolvidos em determinados momentos.
## O Que Vem Depois?
Vamos continuar "Projetando Scripts Reais no Bitcoin" na seção [§13.3: Capacitando o Bitcoin com Scripts](13_3_Empowering_Bitcoin_with_Scripts.md).

View File

@ -0,0 +1,276 @@
# 13.3: Capacitando o Bitcoin com Scripts
Os scripts do Bitcoin podem ir muito além dos instrumentos financeiros relativamente simples detalhados até o momento. Eles também são a base dos usos mais complexos da rede Bitcoin, conforme demonstrado por esses exemplos do mundo real de funcionalidade fora da blockchain (off-chain), extraídos dos exemplos da Lightning Network no [BIP 112](https://github.com/bitcoin /bips/blob/master/bip-0112.mediawiki).
## Bloqueio para a Lightning Network
A [Lightning Network](https://rusty.ozlabs.org/?p=450) é um canal de pagamento que permite aos usuários retirar fundos off-chain e se envolver em várias micro-transações antes de finalizar o canal de pagamento e trazer os fundos de volta para o Bitcoin. Os benefícios incluem taxas mais baixas e velocidades de transação mais rápidas. Iremos discutir em mais detalhes, com exemplos de como utilizá-la usando a linha de comando, começando no [Capítulo 19](19_0_Understanding_Your_Lightning_Setup.md).
O [BIP 112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki) contém alguns exemplos de como essas transações off-chain poderiam ser geradas, usando scripts de bloqueio do Bitcoin.
### Bloqueio com Transações de Compromisso Revogáveis
O truque com a Lightning é o fato de ela estar off-chain. Para usar a Lightning, os participantes bloqueiam fundos em conjunto na blockchain do Bitcoin com uma transação multisig n-de-n. Em seguida, eles se envolvem em uma série de transações entre si. Cada nova "transação de compromisso" (commitment transaction) divide esses fundos de uma maneira diferente. Essas transações são parcialmente assinadas, mas _não são colocadas na blockchain_.
Se temos uma massa de transações não publicadas, qualquer uma delas _pode_ ser colocada na Blockchain, portanto, como evitamos que um dos participantes reverta a uma transação antiga que é mais benéfica para eles? A resposta é _revogação_. Um exemplo simplificado no BIP 112, que oferece um dos trampolins para a Lightning, mostra o processo. Nós damos ao participante que seria prejudicado pela reversão de uma transação revogada a capacidade de retirar os fundos ele mesmo se o outro participante tentar usar ilegitimamente a transação revogada.
Por exemplo, suponha que Alice e Bob atualizem a transação de compromisso para dar mais fundos a Bob (ou seja, Alice enviou fundos a Bob por meio da rede Lightning). Eles assinam parcialmente novas transações, mas cada um também oferece seu próprio ```revokeCode``` para as transações anteriores. Isso efetivamente garante que nenhum deles irão publicar as transações anteriores, porque isso permitiria que a contraparte reivindicasse os fundos anteriores.
Então, como se parece a transação antiga? Foi uma transação de compromisso mostrando fundos destinados a Alice, antes que ela os desse a Bob. Ele tinha um script de bloqueio da seguinte maneira:
```
OP_HASH160
<revokeHash>
OP_EQUAL
IF
<pubKeyBob>
ELSE
<+24Hours>
OP_CHECKSEQUENCEVERIFY
OP_DROP
<pubKeyAlice>
ENDIF
OP_CHECKSIG
```
O bloco ```ELSE``` é onde Alice conseguiu os fundos, após um atraso de 24 horas. No entanto, agora foi substituído. Afinal, esse é o ponto principal de um canal de pagamento na Lightning. Nesta situação, esta transação nunca deve ser publicada. Bob não tem incentivo para isso porque ele tem uma transação mais recente, que o beneficia mais porque ele recebeu parte dos fundos de Alice. Alice também não tem incentivo, porque ela perde o dinheiro se tentar retirar mais do que deve, por conta do ```revokeCode```. Assim, ninguém coloca a transação na blockchain e as transações off-chain continuam.
Vale a pena explorar como esse script funcionaria em uma variedade de situações, a maioria das quais envolve Alice tentando trapacear, revertendo para a transação mais antiga, que descreve os fundos _antes_ da Alice enviar os satoshis para Bob.
#### Executando o Script de Bloqueio para a Alice Trapaceira, com Código de Revogação
Alice poderia tentar usar o código de revogação que ela deu a Bob para reivindicar imediatamente os fundos. Ela escreve um script de bloqueio de ```<sigAlice> <revokeCode>```:
```
Script: <sigAlice> <revokeCode> OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Stack: [ ]
Script: OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Stack: [ <sigAlice> <revokeCode> ]
Script: <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Running: <revokeCode> OP_HASH160
Stack: [ <sigAlice> <revokeHash> ]
Script: OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Stack: [ <sigAlice> <revokeHash> <revokeHash> ]
Script: IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Running: <revokeHash> <revokeHash> OP_EQUAL
Stack: [ <sigAlice> True ]
```
O ```OP_EQUAL``` alimenta a instrução ```IF```. Como Alice usa o ```revokeCode```, ela entra no caminho que permite gatar os fundos imediatamente, reduzindo o resto do script para ```<pubKeyBob>``` (dentro do condicional) e com o ```OP_CHECKSIG``` (depois).
```
Script: <pubKeyBob> OP_CHECKSIG
Running: True IF
Stack: [ <sigAlice> ]
```
Maldição! Apenas Bob pode assinar imediatamente usando o ```redeemCode```!
```
Script: OP_CHECKSIG
Stack: [ <sigAlice> <pubKeyBob> ]
Script:
Running: <sigAlice> <pubKeyBob> OP_CHECKSIG
Stack: [ False ]
```
#### Executando o Script de Bloqueio para a Alice Trapaceira, sem Código de Revogação
E se Alice tentar usar sua própria assinatura, sem o ```revokeCode```? Ela usa um script de desbloqueio de ```<sigAlice> <notRevokeCode>```.
```
Script: <sigAlice> 0 OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Stack: [ ]
Script: OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Stack: [ <sigAlice> 0 ]
Script: <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Running: 0 OP_HASH160
Stack: [ <sigAlice> <0Hash> ]
Script: OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Stack: [ <sigAlice> <0Hash> <revokeHash> ]
Script: IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Running: <0Hash> <revokeHash> OP_EQUAL
Stack: [ <sigAlice> False ]
```
Agora reduzimos para a instrução ```ELSE``` e o que vem depois do condicional:
```
Script: <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> OP_CHECKSIG
Running: False IF
Stack: [ <sigAlice> ]
Script: OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> OP_CHECKSIG
Stack: [ <sigAlice> <+24Hours> ]
```
E então Alice é frustrada de novo porque 24 horas não se passaram!
```
Script: OP_DROP <pubKeyAlice> OP_CHECKSIG
Running: <+24Hours> OP_CHECKSEQUENCEVERIFY
Stack: [ <sigAlice> <+24Hours> ] — Script EXITS
```
#### Executando o Script de Bloqueio para o Bob Vitimizado
O que isso significa é que Bob tem 24 horas para recuperar os fundos se Alice tentar trapacear, usando o ```<revokeCode>``` e a assinatura como script de desbloqueio:
```
Script: <SigBob> <revokeCode> OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Stack: [ ]
Script: OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Stack: [ <SigBob> <revokeCode> ]
Script: <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Running: <revokeCode> OP_HASH160
Stack: [ <SigBob> <revokeHash> ]
Script: OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Stack: [ <SigBob> <revokeHash> <revokeHash> ]
Script: IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
Running: <revokeHash> <revokeHash> OP_EQUAL
Stack: [ <SigBob> True ]
Script: <pubKeyBob> OP_CHECKSIG
Running: True IF
Stack: [ <SigBob> ]
Script: OP_CHECKSIG
Stack: [ <SigBob> <pubKeyBob> ]
Script:
Running: <SigBob> <pubKeyBob> OP_CHECKSIG
Stack: [ True ]
```
#### Executando o Script de Bloqueio para a Alice Virtuosa
Todas as transações de confirmação da Alice são bloqueadas com este mesmo script de bloqueio, quer tenham sido revogadas ou não. Isso significa que a transação de confirmação mais recente, que é a válida atualmente, também está bloqueada com ela. Alice nunca enviou uma transação mais recente para Bob e, portanto, nunca enviou a ele o ```revokeCode``` anterior.
Nessa situação, ela poderia publicar virtuosamente a transação, fechando o canal. Ela coloca a transação na blockchain e espera 24 horas. Bob não pode fazer nada a respeito porque não possui o código de recuperação. Então, após a espera, Alice recupera os fundos. Bob pode fazer a mesma coisa com sua própria transação final.
### Bloqueando com Contratos de Bloqueio de Tempo em Hash
As Transações de Compromisso Revogável foram apenas um trampolim para a Lightning. A Lightning Network real usa um mecanismo mais complexo chamado [Contrato de Bloqueio de Tempo em Hash (ou no inglês, Hashed TimeLock Contract)](https://en.bitcoin.it/wiki/Hashed_Timelock_Contracts), mais conhecido como HTLC.
O principal objetivo dos HTLCs é criar uma rede abrangente de participantes. As transações não são mais apenas entre um par de participantes que entraram na rede juntos, mas agora podem ser várias pessoas que não estão associadas diretamente. Quando os fundos são enviados, uma string de transações é criada, cada uma delas bloqueada com um ```secretHash```. Quando o ```secretCode``` correspondente é revelado, toda a sequência de transações pode ser gasta. Isso é o que permite que transações singulares realmente se tornem uma rede.
Também há um pouco mais de complexidade nos scripts de bloqueio da Lightning Network. Existem bloqueios separados para o remetente e o destinatário de cada transação que são mais amplamente divergentes do que as diferentes transações de compromisso mencionadas na seção anterior. Vamos mostrar os dois, para demonstrar o poder desses scripts de bloqueio, mas não vamos explicar como eles interagem entre si.
#### Bloqueando a Transação do Destinatário
Mais uma vez, vamos começar a olhar para a transação de compromisso da Alice, que mostra os fundos que ela recebeu:
```
OP_HASH160
OP_DUP
<secretHash>
OP_EQUAL
IF
<+24Hours>
OP_CHECKSEQUENCEVERIFY
OP_2DROP
<pubKeyAlice>
ELSE
<revokeHash>
OP_EQUAL
OP_NOTIF
<Date>
OP_CHECKLOCKTIMEVERIFY
OP_DROP
ENDIF
<pubKeyBob>
ENDIF
OP_CHECKSIG
```
A chave para esses novos HTLCs é o ```secretHash```, que dissemos que é o que permite que uma transação se estenda pela rede. Quando a transação vai do remetente ao destinatário pretendido, o ```secretCode``` é revelado, o que permite que todos os participantes criem um ```secretHash``` e desbloqueiem toda a rede de pagamentos.
Após o ```secretCode``` ter sido revelado, o caminho do ```IF``` é utilizado. Alice pode reivindicar os fundos 24 horas após a transação ser colocada na rede Bitcoin.
No entanto, também há a oportunidade de Bob recuperar os fundos, que aparecem no caminho do ```ELSE```. Ele pode fazer isso se a transação foi revogada (mas Alice a coloca na blockchain de qualquer maneira), _ou se_ um tempo absoluto se esgotar (timeout).
#### Bloqueando a Transação do Remetente
Este é o script alternativo de bloqueio da transação de confirmação usado pelo remetente:
```
OP_HASH160
OP_DUP
<secretHash>
OP_EQUAL
OP_SWAP
<revokeHash>
OP_EQUAL
OP_ADD
IF
<pubKeyAlice>
ELSE
<Date>
OP_CHECKLOCKTIMEVERIFY
<+24Hours>
OP_CHECKSEQUENCEVERIFY
OP_2DROP
<pubKeyBob>
ENDIF
OP_CHECKSIG
```
A parte inicial do script é bastante inteligente e vale a pena executá-la:
```
Initial Script: <suppliedCode> OP_HASH160 OP_DUP <secretHash> OP_EQUAL OP_SWAP <revokeHash> OP_EQUAL OP_ADD
Stack: [ ]
Initial Script: OP_HASH160 OP_DUP <secretHash> OP_EQUAL OP_SWAP <revokeHash> OP_EQUAL OP_ADD
Stack: [ <suppliedCode> ]
Initial Script: OP_DUP <secretHash> OP_EQUAL OP_SWAP <revokeHash> OP_EQUAL OP_ADD
Running: <suppliedCode> OP_HASH160
Stack: [ <suppliedHash> ]
Initial Script: <secretHash> OP_EQUAL OP_SWAP <revokeHash> OP_EQUAL OP_ADD
Running: <suppliedHash> OP_DUP
Stack: [ <suppliedHash> <suppliedHash> ]
Initial Script: OP_EQUAL OP_SWAP <revokeHash> OP_EQUAL OP_ADD
Stack: [ <suppliedHash> <suppliedHash> <secretHash> ]
Initial Script: OP_SWAP <revokeHash> OP_EQUAL OP_ADD
Running: <suppliedHash> <secretHash> OP_EQUAL
Stack: [ <suppliedHash> <wasItSecretHash?> ]
Initial Script: <revokeHash> OP_EQUAL OP_ADD
Running: <suppliedHash> <wasItSecretHash?> OP_SWAP
Stack: [ <wasItSecretHash?> <suppliedHash> ]
Initial Script: OP_EQUAL OP_ADD
Stack: [ <wasItSecretHash?> <suppliedHash> <revokeHash> ]
Initial Script: OP_ADD
Running: <suppliedHash> <revokeHash> OP_EQUAL
Stack: [ <wasItSecretHash?> <wasItRevokeHash?> ]
Initial Script:
Running: <wasItSecretHash?> <wasItRevokeHash?> OP_ADD
Stack: [ <wasItSecretOrRevokeHash?> ]
```
A execução do script revela que as verificações iniciais, acima do ```IF```/```ELSE```/```ENDIF```, determinam se o hash era _tanto_ o ```secretCode``` _ou_ o ```revokeCode```. Nesse caso, Alice pode pegar os fundos no primeiro bloco. Do contrário, Bob pode pegar os fundos, mas somente depois que Alice tiver sua chance e depois que o tempo limite de 24 horas e o tempo limite absoluto tiverem se esgotado.
#### Compreendendo os HTLCs
Os HTLCs são bastante complexos e esta seção não tenta explicar todas as suas complexidades. A [visão geral](https://rusty.ozlabs.org/?p=462) escrita por Rusty Russell explica bem mais, e há ainda mais detalhes no seu artigo [Deployable-lightning](https://github.com/ElementsProject/lightning/blob/master/doc/deployable-lightning.pdf). Mas não se preocupe se algumas das complexidades ainda não ficaram claras para você, especialmente sobre o funcionamento das inter-relações dos dois scripts.
Para os fins deste tutorial, existem duas lições importantes em relação aos HTLCs:
* Entender que uma estrutura muito complexa como um HTLC pode ser criada usando o Bitcoin Script;
* Analisar como executar cada um dos scripts HTLC.
Vale a pena executar cada um dos dois scripts HTLC em cada uma de permutações, um item da pilha de cada vez.
## Resumo: Capacitando o Bitcoin com Scripts
Estamos encerrando o exame dos scripts do Bitcoin com uma visão de como eles podem ser realmente poderosos. Com 20 opcodes ou menos, um script Bitcoin pode formar a base de todo um canal de pagamento fora da blockchain. Da mesma forma, sidechains com conexões bidirecionais são o produto de menos de vinte opcodes, como também observado brevemente no [BIP 112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki).
Se você já viu funcionalidades complexas do Bitcoin ou sistemas adjacentes ao Bitcoin, eles provavelmente foram construídos em Bitcoin Script. E agora temos todas as ferramentas para fazer o mesmo.
## O Que Vem Depois?
Vamos ficar "Usando o Tor" no [Capítulo Quatorze: Usando o Tor](14_0_Using_Tor.md).
Ou, se preferir, existem dois caminhos alternativos:
Se quiser manter o foco no Bitcoin, siga em frente para "Programando com RPC" no [Capítulo Dezesseis: Conversando com Bitcoind com C](16_0_Talking_to_Bitcoind.md).
Ou, se quiser manter o foco na linha de comando porque não é um programador, pode pular para o [Capítulo Dezenove: Compreendendo Nossa Configuração da Lightning](19_0_Understanding_Your_Lightning_Setup.md) para continuar seus estudos da linha de comando com a Lightning Network.

21
pt/14_0_Using_Tor.md Normal file
View File

@ -0,0 +1,21 @@
# Capítulo 14: Usando o Tor
O Tor é um dos programas padrão instalados pelo [Bitcoin Standup](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts). Ele nos ajuda a manter nosso servidor seguro, o que é extremamente importante quando estamos lidando com Bitcoin. Este capítulo divaga um pouco do nosso objetivo para nos ajudar a entender essa infraestrutura de segurança.
## Objetivos deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Usar uma configuração Tor;
* Fazer a manutenção do Tor.
Os objetivos secundários incluem a capacidade de:
* Compreender a rede Tor;
* Compreender as várias portas do Bitcoin.
## Tabela de Conteúdo
* [Seção 1: Verificando Nossa Configuração do Tor](14_1_Verifying_Your_Tor_Setup.md)
* [Seção 2: Mudando Nossos Serviços Ocultos do Bitcoin](14_2_Changing_Your_Bitcoin_Hidden_Services.md)
* [Seção 3: Adicionando Serviços SSH Ocultos](14_3_Adding_SSH_Hidden_Services.md)

View File

@ -0,0 +1,365 @@
# 14.1: Verificando Nossa Configuração do Tor
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Se fizéssemos uma instalação padrão com o [Bitcoin Standup](https://github.com/BlockchainCommons/Bitcoin-Standup), provavelmente já teríamos o Tor configurado como parte do nosso node Bitcoin. O Tor está instalado e já criou os serviços ocultos para as portas RPC do Bitcoin, enquanto um endereço Onion também foi criado para o ```bitcoind```. Nesta seção iremos discutir tudo isso e o que fazer com essas informações e ferramentas.
> :book: ***O que é o Tor?*** O Tor é uma rede de sobreposição e anonimato de baixa latência baseada no design de roteamento e construção de caminhos para permitir a comunicação anônima. É um software gratuito e open source com o nome derivado da sigla do nome do projeto de software original: "The Onion Router".
> :book: ***Por que usar o Tor com o Bitcoin?*** A rede Bitcoin é uma rede peer-to-peer que escuta as transações e as propaga usando um endereço IP público. Ao conectar-se à rede sem o Tor, iríamos compartilhar nosso endereço IP, o que poderia expor nossa localização, o tempo de atividade e outros detalhes a terceiros, o que é uma prática de privacidade indesejável. Para nos protegermos virtualmente, devemos usar ferramentas como o Tor para ocultar os detalhes da nossa conexão. O Tor permite melhorar nossa privacidade online, pois os dados são codificados criptograficamente e passam por nodes diferentes, cada um decodificando uma única camada (por isso a metáfora da cebola).
## Entendendo o Tor
Então, como o Tor funciona?
Quando um usuário deseja se conectar a um servidor na Internet, o Tor tenta construir um caminho formado por pelo menos três retransmissores de nodes do Tor, chamados de Guarda, Meio e Saída. Durante a construção desse caminho, as chaves de criptografia simétricas são negociadas. Quando uma mensagem se move ao longo do caminho, cada retransmissão remove sua camada de criptografia. Dessa forma, a mensagem chega ao destino final na forma original, e cada parte conhece apenas o salto anterior e o próximo e não pode determinar a origem ou o destino.
Esta é a aparência de uma conexão sem o Tor:
```
20:58:03.804787 IP bitcoin.36300 > lb-140-82-114-25-iad.github.com.443: Flags [P.], seq 1:30, ack 25, win 501, options [nop,nop,TS val 3087919981 ecr 802303366], length 29
```
Agora, com o Tor, muito menos informações sobre as máquinas reais são transmitidas:
```
21:06:52.744602 IP bitcoin.58776 > 195-xxx-xxx-x.rev.pxxxxxm.eu.9999: Flags [P.], seq 264139:265189, ack 3519373, win 3410, options [nop,nop,TS val 209009853 ecr 3018177498], length 1050
21:06:52.776968 IP 195-xxx-xxx-x.rev.pxxxxxm.eu.9999 > bitcoin.58776: Flags [.], ack 265189, win 501, options [nop,nop,TS val 3018177533 ecr 209009853], length 0
```
Resumindo: o Tor criptografa nossos dados de forma a ocultar nossa origem, destino e quais serviços estamos usando, enquanto um protocolo de criptografia padrão como TLS *apenas* protege o conteúdo dos nossos dados.
### Compreendendo a Arquitetura da Rede Tor
A arquitetura básica da rede Tor é composta pelos seguintes componentes:
* **Cliente Tor (OP ou Onion Proxy).** Um cliente Tor instala o software local que atua como um proxy onion. Ele empacota os dados do aplicativo em células do mesmo tamanho (512 bytes), que então envia para a rede Tor. Uma célula é a unidade básica de transmissão do Tor.
* **Node Onion (OR ou Onion Router).** Um Node Onion transmite células provenientes do cliente Tor e de servidores online. Existem três tipos de Nodes Onion: nodes de entrada (Guarda), nodes intermediários (Meio) e nodes de saída (Saída).
* **Servidor de Diretório.** Um servidor de diretório armazena informações sobre roteadores e servidores onion (serviços ocultos), como as suas chaves públicas.
* **Onion Server (Servidor Oculto).** Um servidor onion oferece suporte a aplicativos TCP, como páginas da web ou IRC, como serviços.
### Compreendendo as Limitações do Tor
O Tor não é uma ferramenta perfeita. Como as informações da rede Tor são descriptografadas nos nodes de saída antes de serem enviadas aos destinos finais, teoricamente um observador poderia coletar metadados suficientes para comprometer o anonimato e potencialmente identificar os usuários.
Também há estudos que sugerem que possíveis explorações da proteção anti-DoS do Bitcoin podem permitir que um invasor force outros usuários que usam o Tor a se conectar exclusivamente por meio dos nodes de saída do Tor ou dos seus pares Bitcoin, isolando o cliente do resto da rede Bitcoin e expondo-o a censura, correlação e demais ataques.
Da mesma forma, os usuários do Bitcoin Tor podem ser atacados por impressão digital (fingerprinting) definindo um cookie de endereço nos nodes. Isso também permitiria a correlação e, portanto, acabando com o anonimato.
Enquanto isso, mesmo no Tor, o Bitcoin é apenas um serviço pseudo-anônimo devido aos muitos perigos de correlação que se originam do próprio livro-razão permanente. Isso significa que o uso do Bitcoin sobre o Tor tem mais probabilidade de _perder o anonimato_ do que outros serviços (e pode levar ao anonimato de outras atividades).
Com isso dito, o Tor é geralmente considerado mais seguro do que a alternativa, que é a navegação não anônima.
## Verificando a Nossa Configuração do Tor
Então, como verificamos se o Tor está ativado? Se o instalamos com o Bitcoin Standup, podemos verificar se o Tor está sendo executado em nosso sistema:
```
$ sudo -u debian-tor tor --verify-config
```
Se o Tor estiver instalado corretamente, devemos obter a seguinte resposta:
```
Jun 26 21:52:09.230 [notice] Tor 0.4.3.5 running on Linux with Libevent 2.0.21-stable, OpenSSL 1.0.2n, Zlib 1.2.11, Liblzma 5.2.2, and Libzstd N/A.
Jun 26 21:52:09.230 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
Jun 26 21:52:09.230 [notice] Read configuration file "/etc/tor/torrc".
Configuration was valid
```
> :warning: **AVISO:** Isso significa apenas que o Tor está sendo executado, não que está sendo usado para todas (ou algumas) conexões.
### Verificando a Nossa Configuração do Tor para o RPC
O propósito mais importante do Tor, conforme instalado pelo Bitcoin Standup, é oferecer serviços ocultos para as portas RPC que são usadas para enviar comandos para o ```bitcoind```.
> :book: ***O que é um serviço oculto do Tor?*** Um serviço oculto (também conhecido como "um onion service") é um serviço que pode ser acessado via Tor. A conexão feita a esse serviço _usando a Onion Network_ será anônima.
O arquivo de configuração do Tor pode ser encontrado em ```/etc/tor/torrc```. Se olharmos para ele, veremos os seguintes serviços que protegem nossas portas do RPC:
```
HiddenServiceDir /var/lib/tor/standup/
HiddenServiceVersion 3
HiddenServicePort 1309 127.0.0.1:18332
HiddenServicePort 1309 127.0.0.1:18443
HiddenServicePort 1309 127.0.0.1:8332
```
> :link: **TESTNET vs MAINNET:** Na Mainnet o RPC é executado na porta 8332, já na testnet, na porta 18332.
> :information_source: **NOTA:** O ```HiddenServiceDir``` é onde todos os arquivos são mantidos para este serviço em particular. Se precisarmos pesquisar nosso endereço onion, chaves de acesso ou adicionar clientes autorizados, é aqui que iremos alterar!
A maneira fácil de testar o nosso Serviço Oculto RPC é usar o [QuickConnect API](https://github.com/BlockchainCommons/Bitcoin-Standup/blob/master/Docs/Quick-Connect-API.md) integrado ao Bitcoin Standup. Basta baixar o código QR que encontramos em ```/qrcode.png``` e digitalizá-lo usando uma carteira ou node que suporte o QuickConnect, como [a Gordian Wallet](https://github.com/BlockchainCommons/FullyNoded-2). Ao escanear o QR, devemos ver a carteira sincronizada com o nosso node. Estaremos fazendo isso usando os serviços ocultos do RPC.
A maneira difícil de testar nosso Serviço Oculto RPC é enviar um comando ```bitcoin-cli``` com o ```torify```, que permite traduzir um comando UNIX normal para um comando protegido por Tor. É algo difícil porque precisamos obter três informações.
1. **Nossa porta de serviço oculta.** Isso pode ser obtido em ```/etc/tor/torrc/```. Por padrão, é a porta 1309.
2. **Nosso endereço Tor.** Essa informação encontra-se no arquivo ```hostname``` no diretório ```HiddenServiceDir``` definido em ```/etc/tor/torrc```. Por padrão, o arquivo pode ser encontrado em ```/var/lib/tor/standup/hostname```. Ele está protegido, então precisaremos usar o ```sudo``` para acessá-lo:
```
$ sudo more /var/lib/tor/standup/hostname
mgcym6je63k44b3i5uachhsndayzx7xi4ldmwrm7in7yvc766rykz6yd.onion
```
3. **Nossa senha do RPC.** Que está no arquivo ```~/.bitcoin/bitcoin.conf```
Quando tivermos todas essas informações, podemos emitir um comando ```bitcoin-cli``` usando o ```torify``` e especificando o ```-rpcconnect``` como nosso endereço onion, o ```-rpcport``` como nossa porta de serviço oculta, e o ```-rpcpassword``` como sendo nossa senha:
```
$ torify bitcoin-cli -rpcconnect=mgcym6je63k44b3i5uachhsndayzx7xi4ldmwrm7in7yvc766rykz6yd.onion -rpcport=1309 -rpcuser=StandUp -rpcpassword=685316cc239c24ba71fd0969fa55634f getblockcount
```
### Verificando Nossa Configuração do Tor para o Bitcoind
O Bitcoin Standup também garante que nosso ```bitcoind``` esteja configurado para se comunicar opcionalmente em um endereço onion.
Podemos verificar a configuração inicial do Tor para o ```bitcoind``` executando grep para "tor" no ```debug.log``` em nosso diretório de dados:
```
$ grep "tor:" ~/.bitcoin/testnet3/debug.log
2021-06-09T14:07:04Z tor: ADD_ONION successful
2021-06-09T14:07:04Z tor: Got service ID vazr3k6bgnfafmdpcmbegoe5ju5kqyz4tk7hhntgaqscam2qupdtk2yd, advertising service vazr3k6bgnfafmdpcmbegoe5ju5kqyz4tk7hhntgaqscam2qupdtk2yd.onion:18333
2021-06-09T14:07:04Z tor: Cached service private key to /home/standup/.bitcoin/testnet3/onion_v3_private_key
```
> :information_source: **NOTA:** O Bitcoin Core não suporta mais endereços v2. O suporte ao Tor v2 foi removido no Pull Request [#22050](https://github.com/bitcoin/bitcoin/pull/22050)
> **TESTNET vs MAINNET:** Na Mainnet o ```bitcoind``` responde usando a porta 8333, na testnet, na porta 18333.
Podemos verificar se um serviço oculto Tor foi criado para o Bitcoin usando o comando RPC ```getnetworkinfo```:
```
$ bitcoin-cli getnetworkinfo
...
"localaddresses": [
{
"address": "173.255.245.83",
"port": 18333,
"score": 1
},
{
"address": "2600:3c01::f03c:92ff:fe86:f26",
"port": 18333,
"score": 1
},
{
"address": "vazr3k6bgnfafmdpcmbegoe5ju5kqyz4tk7hhntgaqscam2qupdtk2yd.onion",
"port": 18333,
"score": 4
}
],
...
```
Isso mostra três endereços para acessarmos nosso servidor Bitcoin, um endereço IPv4 (```173.255.245.83```), um endereço IPv6 (```2600:3c01::f03c:92ff:fe86:f26```), e um endereço Tor (```vazr3k6bgnfafmdpcmbegoe5ju5kqyz4tk7htgtgaq2qudsc```).
> :warning: **AVISO:** Obviamente, nunca podemos revelar seu endereço Tor de uma forma que esteja associada ao nosso nome ou a outras PII ("personably identifiable information", ou informações de identificação pessoal)!
Podemos ver algumas informações semelhantes com o ```getnetworkinfo```.
```
bitcoin-cli getnetworkinfo
{
"version": 200000,
"subversion": "/Satoshi:0.20.0/",
"protocolversion": 70015,
"localservices": "0000000000000408",
"localservicesnames": [
"WITNESS",
"NETWORK_LIMITED"
],
"localrelay": true,
"timeoffset": 0,
"networkactive": true,
"connections": 10,
"networks": [
{
"name": "ipv4",
"limited": false,
"reachable": true,
"proxy": "",
"proxy_randomize_credentials": false
},
{
"name": "ipv6",
"limited": false,
"reachable": true,
"proxy": "",
"proxy_randomize_credentials": false
},
{
"name": "onion",
"limited": false,
"reachable": true,
"proxy": "127.0.0.1:9050",
"proxy_randomize_credentials": true
}
],
"relayfee": 0.00001000,
"incrementalfee": 0.00001000,
"localaddresses": [
{
"address": "173.255.245.83",
"port": 18333,
"score": 1
},
{
"address": "2600:3c01::f03c:92ff:fe86:f26",
"port": 18333,
"score": 1
},
{
"address": "vazr3k6bgnfafmdpcmbegoe5ju5kqyz4tk7hhntgaqscam2qupdtk2yd.onion",
"port": 18333,
"score": 4
}
],
"warnings": ""
}
```
Este serviço oculto permitirá conexões anônimas com o nosso ```bitcoind``` através da rede Bitcoin.
> :warning: **AVISO:** Executar o Tor e ter um serviço oculto do Tor não nos obriga a usar o Tor.
### Verificando Nossa Configuração do Tor para os Peers
Usando o comando RPC ```getpeerinfo```, podemos ver quais nodes estão conectados ao nosso node e verificar se eles estão conectados ao Tor.
```
$ bitcoin-cli getpeerinfo
```
Alguns podem estar conectados via Tor:
```
...
{
"id": 9,
"addr": "nkv.......xxx.onion:8333",
"addrbind": "127.0.0.1:51716",
"services": "000000000000040d",
"servicesnames": [
"NETWORK",
"BLOOM",
"WITNESS",
"NETWORK_LIMITED"
],
"relaytxes": true,
"lastsend": 1593981053,
"lastrecv": 1593981057,
"bytessent": 1748,
"bytesrecv": 41376,
"conntime": 1593980917,
"timeoffset": -38,
"pingwait": 81.649295,
"version": 70015,
"subver": "/Satoshi:0.20.0/",
"inbound": false,
"addnode": false,
"startingheight": 637875,
"banscore": 0,
"synced_headers": -1,
"synced_blocks": -1,
"inflight": [
],
"whitelisted": false,
"permissions": [
],
"minfeefilter": 0.00000000,
"bytessent_per_msg": {
"addr": 55,
"feefilter": 32,
"getaddr": 24,
"getheaders": 1053,
"inv": 280,
"ping": 32,
"pong": 32,
"sendcmpct": 66,
"sendheaders": 24,
"verack": 24,
"version": 126
},
"bytesrecv_per_msg": {
"addr": 30082,
"feefilter": 32,
"getdata": 280,
"getheaders": 1053,
"headers": 106,
"inv": 9519,
"ping": 32,
"pong": 32,
"sendcmpct": 66,
"sendheaders": 24,
"verack": 24,
"version": 126
}
}
...
```
Alguns podem não estar, como esta conexão IPv6:
```
...
{
"id": 17,
"addr": "[2001:638:a000:4140::ffff:191]:18333",
"addrlocal": "[2600:3c01::f03c:92ff:fe86:f26]:36344",
"addrbind": "[2600:3c01::f03c:92ff:fe86:f26]:36344",
"services": "0000000000000409",
"servicesnames": [
"NETWORK",
"WITNESS",
"NETWORK_LIMITED"
],
"relaytxes": true,
"lastsend": 1595447081,
"lastrecv": 1595447067,
"bytessent": 12250453,
"bytesrecv": 2298711417,
"conntime": 1594836414,
"timeoffset": -1,
"pingtime": 0.165518,
"minping": 0.156638,
"version": 70015,
"subver": "/Satoshi:0.20.0/",
"inbound": false,
"addnode": false,
"startingheight": 1780784,
"banscore": 0,
"synced_headers": 1781391,
"synced_blocks": 1781391,
"inflight": [
],
"whitelisted": false,
"permissions": [
],
"minfeefilter": 0.00001000,
"bytessent_per_msg": {
"addr": 4760,
"feefilter": 32,
"getaddr": 24,
"getdata": 8151183,
"getheaders": 1085,
"headers": 62858,
"inv": 3559475,
"ping": 162816,
"pong": 162816,
"sendcmpct": 132,
"sendheaders": 24,
"tx": 145098,
"verack": 24,
"version": 126
},
"bytesrecv_per_msg": {
"addr": 33877,
"block": 2291124374,
"feefilter": 32,
"getdata": 9430,
"getheaders": 1085,
"headers": 60950,
"inv": 2019175,
"ping": 162816,
"pong": 162816,
"sendcmpct": 66,
"sendheaders": 24,
"tx": 5136622,
"verack": 24,
"version": 126
}
}
...
```
Ter um endereço Tor para nosso ```bitcoind``` é provavelmente um pouco menos útil do que ter um endereço Tor para nossas conexões RPC. Isso é verdade porque não é recomendado tentar enviar todas as nossas conexões Bitcoin via Tor, e em parte porque proteger nossos comandos RPC é o que realmente importa. É muito mais provável que façamos isso remotamente, a partir de uma carteira de software como a Gordian Wallet, enquanto o nosso próprio servidor tem mais probabilidade de estar no escritório, no porão ou em um bunker.
No entanto, existem maneiras de fazer o ```bitcoind``` usar mais o Tor, conforme iremos discutir na próxima seção.
## Resumo: Verificando Nossa Configuração do Tor
O Tor é um pacote de software instalado como parte do Bitcoin Standup que permite a troca de comunicações anonimamente. Ele protegerá nossas portas RPC (8332 ou 18332) e nossas portas do ```bitcoind``` (8333 ou 18333), porém, teremos que nos conectar ativamente ao endereço onion para utilizá-las! O Tor é um pilar fundamental da privacidade e segurança para a nossa configuração do Bitcoin, e podemos verificar se ele está disponível e vinculado ao Bitcoin com alguns comandos simples.
> :fire: ***Qual é o poder do Tor?*** Muitos ataques a usuários de Bitcoin dependem da informação de quem é a vítima e que ela possui Bitcoins. O Tor pode nos proteger disso, escondendo onde estamos e o que estamos fazendo. É particularmente importante se desejamos nos conectar ao nosso próprio node remotamente por meio de uma carteira de software, e pode ser crucial se fizermos isso em algum país onde o uso de Bitcoin é mal visto. Se precisarmos acessar nossos serviços Bitcoin remotamente, precisamos nos certificar de que nossa carteira seja totalmente compatível com o Tor e envie todos os comandos RPC ao nosso servidor usando esse protocolo.
## O Que Vem Depois?
Vamos continuar "Usando o Tor" na seção [§14.2: Mudando Nossos Serviços Ocultos do Bitcoin](14_2_Changing_Your_Bitcoin_Hidden_Services.md).

View File

@ -0,0 +1,74 @@
# 14.2: Mudando Nossos Serviços Ocultos do Bitcoin
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Temos um serviço Tor funcionando, mas com o tempo talvez queiramos reiniciá-lo ou ajustá-lo de outra forma.
## Protejendo Nossos Serviços Ocultos
O Tor permite que limitemos quais clientes conversam com nossos serviços ocultos. Se ainda não autorizamos nosso cliente durante a configuração do servidor, na primeira oportunidade devemos fazer o seguinte:
1. Solicitar uma chave pública de autenticação Tor V3 do nosso cliente. (Na [GordianWallet](https://github.com/BlockchainCommons/GordianWallet-iOS), está disponível no menu de configurações).
2. Vamos para o subdiretório apropriado para nosso serviço oculto do Bitcoin. Se usamos o Bitcoin Standup é ```/var/lib/tor/standup/```.
3. Vamos para o subdiretório ```authorized_clients```.
4. Vamos adicionar um arquivo chamado ```[qualquer coisa].auth```. O ```[qualquer coisa]``` pode ser realmente qualquer coisa.
5. Colocamos a chave pública (e nada mais) no arquivo.
Depois de adicionar um arquivo ```.auth``` ao subdiretório ```authorized_client```, somente os clientes autorizados serão capazes de se comunicar com esse serviço oculto. Podemos adicionar mais ou menos 330 chaves públicas diferentes para habilitar clientes diferentes.
## Redefinindo Nosso Endereço Onion do ```bitcoind```
Se quisermos redefinir nosso endereço onion para o ```bitcoind```, podemos apenas remover o ```onion_private_key``` do nosso diretório de dados, no `~/.bitcoin/testnet`:
```
$ cd ~/.bitcoin/testnet
$ rm onion_private_key
```
Quando reiniciarmos, um novo endereço onion será gerado:
```
2020-07-22T23:52:27Z tor: Got service ID pyrtqyiqbwb3rhe7, advertising service pyrtqyiqbwb3rhe7.onion:18333
2020-07-22T23:52:27Z tor: Cached service private key to /home/standup/.bitcoin/testnet3/onion_private_key
```
## Redefinindo Nosso Endereço Onion do RPC
Se quisermos redefinir nosso endereço onion para o acesso RPC, podemos excluir da mesma forma o ```HiddenServiceDirectory``` apropriado e reiniciar o Tor:
```
$ sudo rm -rf /var/lib/tor/standup/
$ sudo /etc/init.d/tor restart
```
> :warning: **AVISO:** Redefinir o endereço onion do RPC desconectará quaisquer carteiras mobile ou outros serviços que contamos usando a API Quicklink. Por isso, temos que tomar bastante cuidado.
## Forçando o ```bitcoind``` a Usar o Tor
Finalmente, podemos forçar o ```bitcoind``` a usar o onion adicionando o seguinte ao nosso arquivo ```bitcoin.conf```:
```
proxy=127.0.0.1:9050
listen=1
bind=127.0.0.1
onlynet=onion
```
Precisaremos adicionar seed nodes baseados no onion ou outros nodes à nossa configuração, mais uma vez editando o ```bitcoin.conf```:
```
seednode=address.onion
seednode=address.onion
seednode=address.onion
seednode=address.onion
addnode=address.onion
addnode=address.onion
addnode=address.onion
addnode=address.onion
```
Depois, basta reiniciar o ```tor``` e o ```bitcoind```.
Agora devemos estar nos comunicando exclusivamente com o Tor. Mas, a menos que estejamos em um local hostil, esse nível de anonimato provavelmente não é necessário. Também não é particularmente recomendado, pois podemos diminuir muito o número de potenciais peers, criando problemas de censura ou mesmo de correlação. Também podemos começar a sofrer com alta latência. E essa configuração pode nos dar uma falsa sensação de anonimato que realmente não existe na rede Bitcoin.
> :warning: **AVISO:** Esta configuração não foi testada! Use por sua conta e risco!
## Resumo: Mudando Nossos Serviços Ocultos do Bitcoin
Provavelmente nós não precisaremos brincar com os nossos serviços onion depois de verificá-los, mas caso precisemos, aqui está como redefinir um endereço Tor que foi comprometido ou passar a usar exclusivamente o Tor com nosso ```bitcoind``` .
## O Que Vem Depois?
Vamos continuar "Usando o Tor" na seção [14.3: Adicionando Serviços SSH Ocultos](14_3_Adding_SSH_Hidden_Services.md).

View File

@ -0,0 +1,59 @@
# 14.3: Adicionando Serviços SSH Ocultos
>:information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Até agora, usamos o Tor com os nossos serviços Bitcoin, mas também podemos usá-lo para proteger outros serviços em nossa máquina, melhorando a segurança e a privacidade. Esta seção demonstra como fazer isso, introduzindo um serviço ```ssh``` oculto para fazer o login remotamente usando o Tor.
## Criando Serviços SSH Ocultos
Novos serviços são criados adicionando-os ao arquivo ```/etc/tor/torrc```:
```
$ su
# cat >> /etc/tor/torrc << EOF
HiddenServiceDir /var/lib/tor/hidden-service-ssh/
HiddenServicePort 22 127.0.0.1:22
EOF
# exit
```
Eis o que cada coisa significa:
* HiddenServiceDir: Indica que temos um diretório de serviço oculto com a configuração necessária para este caminho.
* HiddenServicePort: Indica a porta Tor a ser usada; no caso do SSH, geralmente é a 22.
Depois de adicionar as linhas apropriadas ao nosso arquivo ```torrc```, precisaremos reiniciar o Tor:
```
$ sudo /etc/init.d/tor restart
```
Após a reinicialização, nosso ```HiddenServiceDir``` deve ter novos arquivos da seguinte forma:
```
$ sudo ls -l /var/lib/tor/hidden-service-ssh
total 16
drwx--S--- 2 debian-tor debian-tor 4096 Jul 22 14:55 authorized_clients
-rw------- 1 debian-tor debian-tor 63 Jul 22 14:56 hostname
-rw------- 1 debian-tor debian-tor 64 Jul 22 14:55 hs_ed25519_public_key
-rw------- 1 debian-tor debian-tor 96 Jul 22 14:55 hs_ed25519_secret_key
```
O arquivo ```hostname``` neste diretório contém nosso novo ID onion:
```
$ sudo cat /var/lib/tor/hidden-service-ssh/hostname
qwkemc3vusd73glx22t3sglf7izs75hqodxsgjqgqlujemv73j73qpid.onion
```
Podemos nos conectar ao serviço oculto ```ssh``` usando o ```torify``` e esse endereço:
```
$ torify ssh standup@qwkemc3vusd73glx22t3sglf7izs75hqodxsgjqgqlujemv73j73qpid.onion
The authenticity of host 'qwkemc3vusd73glx22t3sglf7izs75hqodxsgjqgqlujemv73j73qpid.onion (127.42.42.0)' can't be established.
ECDSA key fingerprint is SHA256:LQiWMtM8qD4Nv7eYT1XwBPDq8fztQafEJ5nfpNdDtCU.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'qwkemc3vusd73glx22t3sglf7izs75hqodxsgjqgqlujemv73j73qpid.onion' (ECDSA) to the list of known hosts.
standup@qwkemc3vusd73glx22t3sglf7izs75hqodxsgjqgqlujemv73j73qpid.onion's password:
```
## Resumo: Adicionando Serviços SSH Ocultos
Agora que instalamos o Tor e sabemos como usá-lo, podemos adicionar outros serviços ao Tor. Apenas adicionamos as linhas ao nosso ```torrc``` (no nosso servidor) e o conectamos com o ```torify``` (no nosso cliente).
> :fire: ***Qual é o poder de utilizar outros serviços ocultos?*** Cada vez que acessamos um serviço em nosso servidor remotamente, deixamos pegadas na rede. Mesmo que os dados sejam criptografados usando SSH (ou TLS), os vigias da rede podem ver de onde estamos nos conectando, para onde estamos conectando e qual serviço estamos usando. Isso realmente importa pra nós? Esta é a pergunta que devemos fazer. Mas se a resposta for "Sim", podemos proteger a conexão com um serviço oculto.
## O Que Vem Depois?
Para um tipo diferente de privacidade, vamos seguir para "Usando o I2P" com o [Capítulo Quize: Usando o I2P](15_0_Using_i2p.md)

20
pt/15_0_Using_i2p.md Normal file
View File

@ -0,0 +1,20 @@
# Capítulo 15: Usando o I2P
Existem alternativas ao Tor. Uma é o Projeto Internet Invisível (I2P, ou Invisible Internet Project em inglês), uma camada de rede privada e totalmente criptografada. Ele utiliza um [banco de dados de rede](https://geti2p.net/pt-br/docs/how/network-database) distribuído e túneis criptografados unidirecionais entre os usuários. A maior diferença do I2P para o Tor é que o segundo é, em essência, uma rede de proxy que oferece serviços de internet de uma forma privada, enquanto que o I2P é fundamentalmente uma rede separada que oferece serviços I2P apenas à rede I2P, criando uma "rede dentro de uma rede". No entanto, podemos querer tê-la apenas como uma alternativa, para que não dependamos apenas do Tor.
No momento, o I2P não está instalada com o [Bitcoin Standup](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts) porque o suporte ao I2P foi adicionado recentemente ao Bitcoin Core. No entanto, neste capítulo, iremos explicar como podemos instalá-lo manualmente.
## Objetivos para Este Capítulo
Depois de trabalharmos neste capítulo, um desenvolvedor será capaz de:
- Executar o Bitcoin Core como um serviço I2P.
Objetivos secundários incluem a habilidade de:
- Compreender a rede I2P;
- Aprender a diferença entre o Tor e o I2P.
## Tabela de Conteúdo
* [Seção Um: Bitcoin Core como um Serviço I2P (Projeto Internet Invisível)](15_1_i2p_service.md)

124
pt/15_1_i2p_service.md Normal file
View File

@ -0,0 +1,124 @@
# 15.1: Bitcoin Core como um Serviço I2P (Projeto Internet Invisível)
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e ainda é um rascunho inicial que pode estar aguardando revisão. Proceda com cuidado, leitor.
Ao invés de utilizarmos o serviço baseado em proxy do Tor para garantir a privacidade das nossas comunicações no Bitcoin, podemos querer utilizar o I2P, que é projetado para agir como uma rede privada dentro da internet, ao invés de simplesmente oferecer acesso privado a serviços de internet.
## Compreendendo as Diferenças
Tanto o Tor quanto o I2P oferecem acesso privado a serviços online, mas com roteamentos, bancos de dados e arquiteturas para retransmissões diferentes. Como serviços ocultos (como acesso ao Bitcoin) são a base do design do I2P, eles também foram otimizados:
| | Tor | I2P |
| ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| Roteamento | [Onion](https://www.onion-router.net/) | [Garlic](https://geti2p.net/en/docs/how/garlic-routing) |
| Banco de Dados da Rede | [Servidores de Diretório](https://blog.torproject.org/possible-upcoming-attempts-disable-tor-network) Confiáveis | [Banco de Dados de Rede Distribuído](https://geti2p.net/en/docs/how/network-database) |
| Retransmissão | Conexões criptografadas de **mão-dupla** entre cada Retransmissor | Conexões de **mão-única** entre todo servidor em seus túneis |
| Serviços Ocultos | Devagar | Rápido |
Podemos encontrar uma comparação mais detalhada em [geti2p.net](https://geti2p.net/pt-br/comparison/tor).
### Compreenda os Tradeoffs para Limitar as Conexões de Saída
Existem [tradeoffs](https://bitcoin.stackexchange.com/questions/107060/tor-and-i2p-tradeoffs-in-bitcoin-core) caso escolhamos usar apenas o I2P, apenas o Tor, ou ambos. Essas configurações, que limitam conexões de saída na clearnet, são feitas no Bitcoin Core usando o argumento `onlynet` no `bitcoin.conf`.
* `onlynet=onion`, que limita conexões de saída ao Tor, pode expor um node a ataques "Sybil" e criar redes separadas, devido às conexões limitadas entre o Tornet e a clearnet.
* `onlynet=onion` e `onlynet=i2p`, juntas, que executa serviço Onion com serviço I2P, é experimental por enquanto.
## Instalando o I2P
Para instalar o I2P, devemos nos certificar de que configuramos as portas de maneira correta, para então, continuar com o processo.
### Preparando as Portas
Para usar o I2P, devemos abrir as seguintes portas, necessárias para o I2P:
1. **De saída (para a internet):** uma porta aleatória entre 9000 e 31000 é selecionada. É melhor se todas essas portas estiverem abertas para conexões de saída, o que não afeta nossa segurança.
- Podemos checar o status do nosso firewall usando `sudo ufw status verbose`, o que não deve negar conexões de saída por padrão.
2. **De entrada (olhando para a internet)**: opcional. A variedade de portas de entrada são listadas na [documentação do I2P](https://geti2p.net/pt-br/faq#ports)
- Para maximizarmos privacidade, é preferível desabilitarmos as conexões de entrada.
### Executando o I2P
Os comandos à seguir irão executar os serviços I2P no Bitcoin Core:
1. Instalando `i2pd` no Ubuntu:
```
sudo add-apt-repository ppa:purplei2p/i2pd
sudo apt-get update
sudo apt-get install i2pd
```
Para instalarmos em outros sistemas operacionais, podemos ver [a documentação](https://i2pd.readthedocs.io/en/latest/user-guide/install/).
2. [Executando](https://i2pd.readthedocs.io/en/latest/user-guide/run/) o serviço I2P:
```
$ sudo systemctl start i2pd.service
```
3. Para verificar se o I2P está executando, devemos observar a porta 7656:
```
$ ss -nlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.1:7656 0.0.0.0:*
```
4. Devemos adicionar as seguintes linhas no `bitcoin.conf`:
```
i2psam=127.0.0.1:7656
debug=i2p
```
A opção para os logs, `debug=i2p`, é utilizada para observarmos as informações adicionais no debug log sobre nossas configurações e conexões I2P. O lugar padrão para esse arquivo de debug no Linux é: `~/.bitcoin/debug.log`
5. Reiniciando o `bitcoind`
```
$ bitcoind
```
6. Devemos verificar se o I2P foi configurado corretamente olhando o `debug.log`, ou se algum erro apareceu nos logs.
```
2021-06-15T20:36:16Z i2paccept thread start
2021-06-15T20:36:16Z I2P: Creating SAM session with 127.0.0.1:7656
2021-06-15T20:36:56Z I2P: SAM session created: session id=3e0f35228b, my address=bmwyyuzyqdc5dcx27s4baltbu6zw7rbqfl2nmclt45i7ng3ul4pa.b32.i2p:18333
2021-06-15T20:36:56Z AddLocal(bmwyyuzyqdc5dcx27s4baltbu6zw7rbqfl2nmclt45i7ng3ul4pa.b32.i2p:18333,4)
```
O nosso endereço I2P é mencionado nos logs, e termina com _b32.i2p_. Por exemplo `bmwyyuzyqdc5dcx27s4baltbu6zw7rbqfl2nmclt45i7ng3ul4pa.b32.i2p:18333`.
7. Devemos confirmar que `i2p_private_key` foi criado no diretório do Bitcoin Core. A primeira vez que o Bitcoin Core conectar ao roteador I2P, o endereço I2P (e a chave privada correspondente) será automaticamente gerado e salvado em um arquivo chamado *i2p_private_key*:
```
~/.bitcoin/testnet3$ ls
anchors.dat chainstate i2p_private_key settings.json
banlist.dat debug.log mempool.dat wallets
blocks fee_estimates.dat peers.dat
```
8. Devemos verificar que `bitcoin-cli -netinfo` ou `bitcoin-cli getnetworkinfo` retorna o endereço I2P:
```
Local addresses
bmwyyuzyqdc5dcx27s4baltbu6zw7rbqfl2nmclt45i7ng3ul4pa.b32.i2p port 18333 score 4
```
Agora temos um servidor do Bitcoin acessível através da rede I2P no nosso novo endereço local.
## Resumo: Bitcoin Core como um Serviço I2P (Projeto Internet Invisível)
É sempre positivo termos alternativas para privacidade e não dependermos exclusivamente do Tor para executarmos o Bitcoin Core como um serviço oculto. Como I2P foi adicionado recentemente ao Bitcoin Core, poucas pessoas o utilizam. Podemos experimentá-lo e reportar bugs se encontrarmos algum problema.
> :information_source: **NOTA:** Para a implementação oficial do I2P em Java, podemos visitar a [página de download do I2P](https://geti2p.net/en/download) e seguirmos as instruções para nosso Sistema Operacional. Após instalado, podemos abrir uma janela do Terminal e escrever `i2prouter start`. Em seguida, podemos visitar o endereço `127.0.0.1:76571` em um navegador e permitirmos o SAM. Para fazermos isso, selecionamos: "Configure Homepage", então "Clients", e finalmente selecionar o "Play Button" ao lado da Bridge de aplicativo SAM. No lado esquerdo da página, devemos ver uma luz verde próximo a "Shared Clients".
Siga em frente para o "Programando com RPC" no [Capítulo Dezesseis: Conversando com o Bitcoind com C](16_0_Talking_to_Bitcoind.md).
Ou, se não formos programadores, podemos pular para o [Capítulo Dezenove: Compreendendo Sua Configuração Lightning](https://github.com/namcios/Learning-Bitcoin-from-the-Command-Line/blob/portuguese-translation/pt/19_0_Understanding_Your_Lightning_Setup.md) para continuarmos nosso aprendizado da linha de comando com a rede Lightning.

View File

@ -0,0 +1,26 @@
# Capítulo 16: Conversando com Bitcoind com 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 em C com Bibliotecas RPC](16_1_Accessing_Bitcoind_with_C.md)
* [Seção 2: Programando o Bitcoind em C com Bibliotecas RPC](16_2_Programming_Bitcoind_with_C.md)
* [Seção 3: Recebendo Notificações em C com Bibliotecas ZMQ](16_3_Receiving_Bitcoind_Notifications_with_C.md)

View File

@ -0,0 +1,293 @@
# 16.1: Acessando o Bitcoind em C com Bibliotecas RPC
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um esboço que ainda pode estar aguardando revisão. Portanto, leitor, tenha cuidado.
Você já viu uma maneira alternativa de acessar as portas RPC do Bitcoind: Usando o ``curl``, que cobrimos no [Capítulo 4 Prefácio](04_4__interlude_using_curl.md). Interagir com o ``Bitcoind`` através de uma biblioteca de RPC usando C não é diferente do que já vimos, só precisamos de boas bibliotecas para nos auxiliar. Esta seção introduz um pacote chamado ``libbitcoinrpc``, que permite acessar a porta JSON-RPC do ``bitcoind``. Ele usa uma biblioteca ``curl`` para acessar os dados e usa a biblioteca ``jansson`` para codificar e decodificar o JSON.
## Configurando o libbitcoinrpc
Para usar o ``libbitcoinrpc``, precisaremos instalar uma configuração básica C e os pacotes dependentes, que são ``libcurl``, ``libjansson``, e ``libuuid``. Depois faremos isso no seu servidor Standup Bitcoin (ou em qualquer outro servidor Ubuntu).
```
$ sudo apt-get install make gcc libcurl4-openssl-dev libjansson-dev uuid-dev
Suggested packages:
libcurl4-doc libidn11-dev libkrb5-dev libldap2-dev librtmp-dev libssh2-1-dev
The following NEW packages will be installed:
libcurl4-openssl-dev libjansson-dev uuid-dev
0 upgraded, 3 newly installed, 0 to remove and 4 not upgraded.
Need to get 358 kB of archives.
After this operation, 1.696 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
```
Agora, podemos baixar o [libbitcoinrpc no github](https://github.com/gitmarek/libbitcoinrpc/blob/master/readme.md). Vamos clonar ou pegar um arquivo zip, do jeito que preferir.
```
$ sudo apt-get install git
$ git clone https://github.com/gitmarek/libbitcoinrpc
```
> :warning: **ATENÇÃO** Uma alteração no RPC "signrawtransaction" causou uma assinatura com ``libbitcoinrpc`` para o segfault no Bitcoin 0.17 ou superior. O [Pull Request foi submetido](https://github.com/gitmarek/libbitcoinrpc/pull/1/commits) para resolver o problema, mas se ainda não tiver sido feito o merge, podemos simplesmente fazer uma simples mudança no código-fonte para ``src/bitcoinrpc_method.c`` antes de compilarmos.
### Compilando o libbitcoinrpc
Antes de compilarmos e instalarmos o pacote, provavelmente precisaremos ajustar nosso ``$PATH``, para que possamos acessar o ``/sbin/ldconfig``:
```
$ PATH="/sbin:$PATH"
```
Para o Ubuntu, também precisaremos ajustar o ``install_libpath`` no ``makefile`` do ``libbitcoinrpc`` para instalar no ``/usr/lib`` ao invés do ``/usr/local/lib``:
```
$ emacs ~/libbitcoinrpc/Makefile
...
INSTALL_LIBPATH := $(INSTALL_PREFIX)/usr/lib
```
(Se preferir não usar o ``/usr/lib``, precisará alterar o ``etc/ld.so.conf`` ou os arquivos dependentes de maneira apropriada... Porém, para uma configuração de teste em uma máquina de teste, acredito que isso não seja um problema).
Da mesma forma, vamos precisar ajustar o ``install_headerpath`` no ``Makefile`` do ``libbitcoinrpc`` para instalar no caminho ``/usr/include`` ao invés do ``/usr/local/inclusve``:
```
...
INSTALL_HEADERPATH := $(INSTALL_PREFIX)/usr/include
```
Agora, podemos compilar:
```
$ cd libbitcoinrpc
~/libbitcoinrpc$ make
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_err.o -c src/bitcoinrpc_err.c
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_global.o -c src/bitcoinrpc_global.c
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc.o -c src/bitcoinrpc.c
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_resp.o -c src/bitcoinrpc_resp.c
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_cl.o -c src/bitcoinrpc_cl.c
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_method.o -c src/bitcoinrpc_method.c
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -shared -Wl,-soname,libbitcoinrpc.so.0 \
src/bitcoinrpc_err.o src/bitcoinrpc_global.o src/bitcoinrpc.o src/bitcoinrpc_resp.o src/bitcoinrpc_cl.o src/bitcoinrpc_method.o \
-o .lib/libbitcoinrpc.so.0.2 \
-Wl,--copy-dt-needed-entries -luuid -ljansson -lcurl
ldconfig -v -n .lib
.lib:
libbitcoinrpc.so.0 -> libbitcoinrpc.so.0.2 (changed)
ln -fs libbitcoinrpc.so.0 .lib/libbitcoinrpc.so
```
Se tudo correr bem, podemos instalar o pacote:
```
$ sudo make install
Installing to
install .lib/libbitcoinrpc.so.0.2 /usr/local/lib
ldconfig -n /usr/local/lib
ln -fs libbitcoinrpc.so.0 /usr/local/lib/libbitcoinrpc.so
install -m 644 src/bitcoinrpc.h /usr/local/include
Installing docs to /usr/share/doc/bitcoinrpc
mkdir -p /usr/share/doc/bitcoinrpc
install -m 644 doc/*.md /usr/share/doc/bitcoinrpc
install -m 644 CREDITS /usr/share/doc/bitcoinrpc
install -m 644 LICENSE /usr/share/doc/bitcoinrpc
install -m 644 Changelog.md /usr/share/doc/bitcoinrpc
Installing man pages
install -m 644 doc/man3/bitcoinrpc*.gz /usr/local/man/man3
```
## Preparando o Código
``libbitcoinrpc`` tem métodos simples e bem estruturados para conectar-se ao nosso `bitcoind`, executando chamadas RPC e decodificando a resposta.
Para usar o ``libbitcoinrpc``, é importante certificar de que nossos arquivos do código incluam os cabeçalhos apropriados:
``` c
#include <jansson.h>
#include <bitcoinrpc.h>
```
Precisaremos também vincular as bibliotecas apropriadas sempre que possamos compilar:
```
$ cc yourcode.c -lbitcoinrpc -ljansson -o yourcode
```
## Construindo a Conexão
Para construir a conexão com o servidor ``bitcoind`` é necessário alguns simples passos.
Primeiro, inicialize a biblioteca:
```
bitcoinrpc_global_init();
```
Em seguida, vamos conectar ao ``Bitcoind`` com ``bitcoinrpc_cl_init_params``. Os quatro argumentos necessários para o ``bitcoinrpc_cl_init_params`` são o nome de usuário, a senha, o endereço IP e a porta. A esta altura, você deve saber todas essas informações, já que foram necessárias para realizar o trabalho com o [curl](04_4__interlude_using_curl.md). Apenas para recordar, o endereço de IP é 127.0.0.1 e a porta 18332 devem estar corretos para a configuração padrão da testenet descrita neste documento, enquanto podemos encontrar o usuário e a senha no arquivo ``~/.bitcoin/bitcoin.conf``.
```
$ cat bitcoin.conf
server=1
dbcache=1536
par=1
maxuploadtarget=137
maxconnections=16
rpcuser=StandUp
rpcpassword=6305f1b2dbb3bc5a16cd0f4aac7e1eba
rpcallowip=127.0.0.1
debug=tor
prune=550
testnet=1
[test]
rpcbind=127.0.0.1
rpcport=18332
[main]
rpcbind=127.0.0.1
rpcport=8332
[regtest]
rpcbind=127.0.0.1
rpcport=18443
```
Com essas informações, vamos colocá-las no ``bitcoinrpc_cl_init_params``:
``` c
bitcoinrpc_cl_t *rpc_client;
rpc_client = bitcoinrpc_cl_init_params("StandUp", "6305f1b2dbb3bc5a16cd0f4aac7e1eba", "127.0.0.1", 18332);
```
> **MAINNET VS TESTNET:** A porta seria a 8332 caso estivéssemos usando a configuração da rede principal.
Se o ``rpc_client`` for inicializado com sucesso, poderemos enviar os comandos do RPC.
Mais tarde, quando tivermos feito com a conexão de ``bitcoind``, poderemos fechar da seguinte maneira:
``` c
bitcoinrpc_global_cleanup();
```
### Testando o Código de Teste
O código de teste pode ser encontrado [no diretório src com o nome 16_1_testbitcoin.c](../src/16_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](../src/16_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: Acessando o Bitcoind em 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 do 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 com C" no capítulo [16.2: Programando o Bitcoind em C com Bibliotecas RPC](16_2_Programming_bitcoind_with_c.md).

View File

@ -0,0 +1,353 @@
# 16.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 seção [§16.1](16_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 seção [§16.1: Acessando o Bitcoind com C](16_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/16_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: Programando o Bitcoind em 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 com C" na próxima seção [16.3: Recebendo notificações usando C com a biblioteca ZMQ](16_3_Receiving_Bitcoind_Notifications_with_C.md).

View File

@ -0,0 +1,154 @@
# 16.3 Recebendo Notificações em C com Bibliotecas 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 [§16.1](16_1_Accessing_Bitcoind_with_C.md) e [§16.2](16_2_Programming_Bitcoind_with_C.md) introduziram as bibliotecas RPC e JSON no C e, também mostrou uma das vantagens de acessar os comandos RPC do Bitcoin por meio de uma linguagem de programação: A capacidade de criar programas razoavelmente complexos. Este capítulo apresenta uma terceira biblioteca, a [ZMQ](http://zeromq.org/) e, ao fazer isso, revela outra vantagem: a capacidade de monitorar as notificações. Iremos usá-la para codificar para ouvirmos a blockchain.
> :book: ***O que é ZMQ?*** O ZeroMQ (ZMQ) é uma biblioteca de mensagens assíncronas de alto desempenho que fornece uma fila de mensagens. A biblioteca oferece suporte a padrões de mensagens comuns (pub/sub, request/reply, client/server e outros) em uma variedade de transportes (TCP, in-process, inter-process, multicast, WebSocket e mais), tornando mensagens entre processos tão simples quanto mensagens entre threads. Podemos encontrar mais detalhes sobre as notificações do ZMQ e outros tipos de mensagens [neste repositório](https://github.com/Actinium-project/ChainTools/blob/master/docs/chainlistener.md).
## Configurando o ZMQ
Antes de podemos ouvir a blockchain, precisaremos configurar o ``bitcoind`` para permitir as notificações ZMQ. Por isso, precisamos instalar a biblioteca ZMQ para tirar proveito dessas notificações.
### Configurando o ``bitcoind`` para usar o ZMQ
O Bitcoin Core está pronto para ZMQ, mas devemos especificar os endpoints do ZMQ. O ZeroMQ publish-sockets prefixa cada item de dados com um prefixo de tópico arbitrário que permite aos clientes assinantes solicitarem apenas os itens com um prefixo correspondente. Existem atualmente quatro tópicos suportados pelo ``bitcoind``:
```
$ bitcoind --help | grep zmq | grep address
-zmqpubhashblock=<address>
-zmqpubhashtx=<address>
-zmqpubrawblock=<address>
-zmqpubrawtx=<address>
```
Podemos executar o ``bitcoind`` com argumentos de linha de comando para endpoints ZMQ, como mostrado acima, mas também podemos criar um endpoint acessível adicionando linhas apropriadas ao nosso arquivo ``~/.bitcoin/bitcoin.conf`` e reiniciando o sistema.
```
zmqpubrawblock=tcp://127.0.0.1:28332
zmqpubrawtx=tcp://127.0.0.1:28333
```
Podemos então testar se os nossos endpoints estão funcionando usando o RPC ``getzmqnotifications``:
```
$ bitcoin-cli getzmqnotifications
[
{
"type": "pubrawblock",
"address": "tcp://127.0.0.1:28332",
"hwm": 1000
},
{
"type": "pubrawtx",
"address": "tcp://127.0.0.1:28333",
"hwm": 1000
}
]
```
Nosso ``bitcoind`` agora irá emitir as notificações ZMQ
### Instalando o ZMQ
Para aproveitar essas notificações, precisamos de uma biblioteca ZMQ para usar com o C, portanto, estaremos usando uma nova biblioteca ZMQ ao invés da biblioteca ``libbitcoinrpc`` nesta seção, mas no futuro, podemos combinar ambas.
Felizmente, as bibliotecas ZMQ estão disponíveis por meio de pacotes Debian padrão:
```
$ sudo apt-get install libzmq3-dev
$ sudo apt-get install libczmq-dev
```
Agora estamos pronto para escrever o código!
## Escrevendo o Programa de Notificação
O programa C à seguir é um cliente simples que se inscreve em um ponto da conexão ZMQ servido pelo ``bitcoind`` e lê as mensagens recebidas.
O programa requer dois parâmetros: O primeiro é o "servidor", que é o ponto de conexão TCP exposto pelo ``bitcoind``. O segundo é o "tópico", que atualmente é o ``zmqpubhashblock``,``zmqpubhashtx``, ``zmqpubrawblock`` ou ``zmqpubrawtx``. O tópico precisa ter suporte do ``bitcoin.conf`` e o endereço IP e a porta do servidor devem corresponder ao que está definido no arquivo de configuração.
``` c
#include <czmq.h>
int main(int argc, char ** argv) {
char *zmqserver;
char *topic;
if(argc < 3) {
printf("\nUSAGE:\nchainlistener <tcp://localhost:port> <topic>\n\n");
return 0;
} else {
zmqserver = argv[1];
topic = argv[2];
}
```
Abriremos um soquete ZMQ para o servidor e para o tópico definido:
``` c
zsock_t *socket = zsock_new_sub(zmqserver, topic);
assert(socket);
```
Depois, vamos esperar:
``` c
while(1) {
zmsg_t *msg;
int rc = zsock_recv(socket, "m", &msg);
assert(rc == 0);
char *header = zmsg_popstr(msg);
zframe_t *zdata = zmsg_pop(msg);
unsigned int *no = (unsigned int*)zmsg_popstr(msg);
char *data = zframe_strhex(zdata);
int len = zframe_size(zdata);
printf("Size: %d\n", len);
printf("Data: %s", data);
printf("\nNo: %d\n", *no);
free(header);
free(data);
free(no);
free(zdata);
zmsg_destroy(&msg);
sleep(1);
}
```
Enquanto esperamos, observamos as mensagens no soquete ZMQ. Sempre que recebermos uma mensagem, iremos retirá-la da pilha, relatando o número, comprimento e, o os dados que foram importante para nós.
É isso!
Claro, quando terminar o processo, precisamos limpar tudo:
``` c
zsock_destroy(&socket);
return 0;
}
```
### Testando o Código de Notificação
O código-fonte completo está no [diretório src/](../src/16_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: Recebendo Notificações em C com Bibliotecas 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 "Programando com RPC" no [Capítulo 17: Programando o Bitcoin com Libwally](17_0_Programming_with_Libwally.md).

View File

@ -0,0 +1,29 @@
# 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.
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
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* 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.
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 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)

View File

@ -0,0 +1,195 @@
# 17.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. 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 a 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
```
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 um programa? 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/17_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 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.
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 Bitcoin com Libwally" na seção [§17.2: Usando BIP39 na Libwally](17_2_Using_BIP39_in_Libwally.md).

View File

@ -0,0 +1,106 @@
# 17.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 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 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 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 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 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 [§17.1](17_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 Entropia
Usando o `libsodium`, podemos criar 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 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 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
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 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`.
### Vendo a Nossa Seed
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);
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/17_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 BIP39 na Libwally
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 §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 [§17.3: Usando o BIP32 no Libwally](17_3_Using_BIP32_in_Libwally.md).

View File

@ -0,0 +1,142 @@
# 17.3: Usando 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 [§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
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, 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. **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`;
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 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 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:
```
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 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);
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 HD pode, como de costume, ser encontrado no [diretório src/](../src/17_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 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, 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 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 Bitcoin com Libwally" na seção [§17.4: Usando PSBTs na Libwally](17_4_Using_PSBTs_in_Libwally.md).

View File

@ -0,0 +1,376 @@
# 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 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 segue é uma introdução básica 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.
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, 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:
```
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`. 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
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:
```
$ 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
```
E, claro, você pode verificar tudo 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 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 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 de 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,&gtx);
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/17_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 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 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 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 Bitcoin com Libwally" na seção [§17.5: Usando Scripts na Libwally](17_5_Using_Scripts_in_Libwally.md).

View File

@ -0,0 +1,179 @@
# 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, 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 [Script de Quebra-Cabeças](13_1_Writing_Puzzle_Scripts.md) ao qual retornamos de vez em quando:
```
OP_ADD 99 OP_EQUAL
```
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
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 à 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) se divide em:
```
a9 / 14 / 3f58b4f7b14847a9083694b9b3b52a4cea2569ed / 87
```
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.
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 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.
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 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:
```
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 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 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`:
```
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 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 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).
### 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. 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 §17.7.
## Testando Nosso Script de Substituição
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
```
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, 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 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 Bitcoin com Libwally" na seção [§17.6: Usando Outras Funções na Libwally](17_6_Using_Other_Functions_in_Libwally.md).

View File

@ -0,0 +1,125 @@
# 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 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
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` - 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.
* `wally_hmac_sha256`
* `wally_hmac_sha512`
Funções adicionais cobrem derivação de 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` - 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` - 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` - 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 do BIP32
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;
* `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 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 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 do BIP39
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 de PSBT
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
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 o tipo de script de uma transação.
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`
* `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 [§17.5](17_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 do Elements
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 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 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 Bitcoin com Libwally" na seção [§17.7: Integrando Libwally e Bitcoin-CLI](17_7_Integrating_Libwally_and_Bitcoin-CLI.md).

View File

@ -0,0 +1,330 @@
# 17.7: Integrando 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 é 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ça Libwally não.
## Compartilhando uma Transação
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:
```
{
"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, 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:
```
...
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 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
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 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 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
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 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);
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 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 [§16.1](16_1_Accessing_Bitcoind_with_C.md).
```
$ cc genhd-for-import.c -lwallycore -lsodium -ljansson -o genhd-for-import
```
Quando executarmos 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 `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 o checksum:
```
$ 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 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.
```
$ 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 `LibwallyImports`:
```
$ 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 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
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 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`:
```
$ ./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 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 da Libwally.
> :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 18: Conversando com o Bitcoind com Outras Linguagens](18_0_Talking_to_Bitcoind_Other.md).

View File

@ -0,0 +1,26 @@
# Capítulo 18: Conversando com o Bitcoind com Outras Linguagens
Agora devemos ter uma base sólida para trabalhar com Bitcoin usando a linguagem C, não apenas usando as bibliotecas RPC, JSON e ZMQ para interagir diretamente com o `bitcoind`, mas também, utilizando as bibliotecas Libwally para complementar esse trabalho. O C é uma ótima linguagem para prototipagem e abstração, porém provavelmente não é o que estamos usando para programar. Este capítulo, portanto, faz uma apresentação rápida de seis outras linguagens de programação, demonstrando a funcionalidade mais básica do Bitcoin em cada uma, permitindo que possamos expandir as lições da linha de comando e do C para a linguagem de programação que desejarmos.
Cada uma das seções contém aproximadamente as mesmas informações, o foco será: criar uma conexão RPC, examinar a carteira, criar um novo endereço e criar uma transação. No entanto, há alguma mudança entre as linguagens, mostrando diferentes aspectos dos comandos RPC do Bitcoin em diferentes exemplos. Em particular, algumas linguagens usam a metodologia fácil do `sendtoaddress`, enquanto outras usam uma metodologia mais difícil para a criação de uma transação bruta do zero.
## Objetivos Deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Preparar ambientes de desenvolvimento para o Bitcoin para uma variedade de linguagens;
* Usar as funções de carteira em várias linguagens;
* Usar funções de transação em uma variedade de linguagens.
Os objetivos secundários do capítulo incluem a capacidade de:
* Saber mais sobre o Bitcoin RPC por meio de interações com uma variedade de linguagens.
## Tabela de Conteúdo
* [Seção 1: Acessando o Bitcoind com Go](18_1_Accessing_Bitcoind_with_Go.md)
* [Seção 2: Acessando o Bitcoind com Java](18_2_Accessing_Bitcoind_with_Java.md)
* [Seção 3: Acessando o Bitcoind com NodeJS](18_3_Accessing_Bitcoind_with_NodeJS.md)
* [Seção 4: Acessando o Bitcoind com Python](18_4_Accessing_Bitcoind_with_Python.md)
* [Seção 5: Acessando o Bitcoind com Rust](18_5_Accessing_Bitcoind_with_Rust.md)
* [Seção 6: Acessando o Bitcoind com Swift](18_6_Accessing_Bitcoind_with_Swift.md)

View File

@ -0,0 +1,420 @@
# 18.1: Acessando o Bitcoind com Go
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Esta seção explica como interagir com o `bitcoind` usando a linguagem de programação Go e o [btcd rpcclient](https://github.com/btcsuite/btcd/tree/master/rpcclient). É importante observar que ele tem algumas peculiaridades e limitações.
## Configurando o Go
Para nos preparamos para o uso do Go em nossa máquina UNIX, primeiro precisamos instalar o curl, caso ainda não o tenhamos feito:
```
$ sudo apt install curl
```
Então, vamos ler a [página de downloads do Go](https://golang.org/dl/) para obtermos o link para o download mais recente e posteriormente fazer o download usando `curl`. Para uma configuração Debian, vamos querer usar a versão `linux-amd64`:
```
$ curl -O https://dl.google.com/go/go1.15.1.linux-amd64.tar.gz
```
Assim que terminarmos o download, comparamos o hash com o hash na [página de downloads do Go](https://golang.org/dl/):
```
$ sha256sum go1.15.1.linux-amd64.tar.gz
70ac0dbf60a8ee9236f337ed0daa7a4c3b98f6186d4497826f68e97c0c0413f6 go1.15.1.linux-amd64.tar.gz
```
Os hashes devem corresponder. Em caso afirmativo, extraímos o tarball e instalamos o Go em nosso sistema:
```
$ tar xfv go1.15.1.linux-amd64.tar.gz
$ sudo chown -R root:root ./go
$ sudo mv go /usr/local
```
Agora precisamos criar um caminho no Go para especificar nosso ambiente. Abra o arquivo `~ / .profile` com o editor de texto de sua escolha e adicione o seguinte ao final dele:
```
export GOPATH=$HOME/work
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
```
Em seguida, atualizamos nosso perfil:
```
$ source ~/.profile
```
Por fim, vamos criar o diretório para o nosso espaço de trabalho Go:
```
$ mkdir $HOME/work
```
### Configurando o `btcd` e o `rpcclient`
Usaremos o `rpcclient` que advém do `btcd`, uma implementação Bitcoin escrita em Go. Embora o `rpcclient` tenha sido originalmente projetado para funcionar com o full node `btcd` do Bitcoin, ele também funciona com o Bitcoin Core. Ele tem algumas peculiaridades que veremos mais adiante.
Podemos usar o ```go get``` para baixá-lo:
```
$ go get github.com/btcsuite/btcd/rpcclient
```
Para testar seu funcionamento, vmaos navegar até o diretório com os exemplos do Bitcoin Core:
```
$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/bitcoincorehttp
```
Vamos modificar o arquivo `main.go` e inserir os detalhes associados à configuração do Bitcoin Core, que pode ser encontrado no caminho `~ /.bitcoin/bitcoin.conf`:
```
Host: "localhost:18332",
User: "StandUp",
Pass: "6305f1b2dbb3bc5a16cd0f4aac7e1eba",
```
> **MAINNET VS TESTNET:** A porta seria 8332 para uma configuração na Mainnet.
Agora podemos executar um teste:
```
$ go run main.go
```
Devemos ver a contagem de blocos impressa:
```
2020/09/01 11:41:24 Block count: 1830861
```
### Criando um Projeto `rpcclient`
Normalmente, iríamos criar projetos no diretório `~/work/src/myproject/bitcoin`:
```
$ mkdir -p ~/work/src/myproject/bitcoin
$ cd ~/work/src/myproject/bitcoin
```
Cada projeto deve ter os seguintes `imports`:
```
import (
"log"
"fmt"
"github.com/btcsuite/btcd/rpcclient"
)
```
Esta declaração `import` permite que importemos bibliotecas relevantes. Para cada exemplo aqui, precisaremos importar `"log", "fmt"` e `"github.com/btcsuite/btcd/rpcclient"`. Podemos precisar importar bibliotecas adicionais em alguns exemplos.
* O `log` é usado para mostrar mensagens de erro na tela. Após cada vez que o node Bitcoin for chamado, uma instrução `if` irá verificar se há algum erro. Se houver erros, o `log` é usado para imprimi-los;
* O `fmt` é usado para imprimir a saída;
* O `rpcclient` é obviamente a biblioteca do `rpcclient`;
## Construindo Nossa Conexão
Cada função do `bitcoind` no Go começa com a criação da conexão RPC, usando a função `ConnConfig`:
```
connCfg := &rpcclient.ConnConfig{
Host: "localhost:18332",
User: "StandUp",
Pass: "431451790e3eee1913115b9dd2fbf0ac",
HTTPPostMode: true,
DisableTLS: true,
}
client, err := rpcclient.New(connCfg, nil)
if err != nil {
log.Fatal(err)
}
defer client.Shutdown()
```
Os parâmetros da `connCfg` permitem que escolhamos a porta Bitcoin RPC, nome de usuário, senha e se estamos usando a testnet ou mainnet.
> **NOTA:** Novamente, precisamos nos certificar de substituir o `User` e o `Pass` com aqueles encontrados no nosso `~/.bitcoin/bitcon.conf`.
A função `rpcclient.New(connCfg, nil)` configura o`client` para nos conectarmos ao nosso node Bitcoin.
A linha `defer client.Shutdown()` é para desconectar do nosso node Bitcoin, uma vez que a função `main()` termina de ser executada. Após a linha `defer client.Shutdown()` é onde as coisas interessantes acontecem e será muito fácil de utilizar. Isso porque o `rpcclient` ajuda a transformar os comandos `bitcoin-cli` em funções, usando PascalCase. Por exemplo, `bitcoin-cli getblockcount` se transformará em `client.GetBlockCount` no Go.
### Fazendo uma Chamada RPC
Agora, tudo o que precisamos fazer é uma chamada informativa como `GetBlockCount` ou` GetBlockHash` usando nosso `client`:
```
blockCount, err := client.GetBlockCount()
if err != nil {
log.Fatal(err)
}
blockHash, err := client.GetBlockHash(blockCount)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%d\n", blockCount)
fmt.Printf("%s\n", blockHash.String())
```
### Fazendo uma Chamada RPC com Argumentos
As funções `rpcclient` também podem receber entradas, por exemplo, `client.GetBlockHash(blockCount)` recebe a contagem de blocos como uma entrada. O `client.GetBlockHash (blockCount)` de cima seria parecido com um comando `bitcoin-cli`:
```
$ bitcoin-cli getblockhash 1830868
00000000000002d53b6b9bba4d4e7dc44a79cebd1024d1bcfb9b3cc07d6cad9c
```
No entanto, uma peculiaridade com hashes no `rpcclient` é que normalmente eles irão ser mostrados em uma codificação diferente se imprimirmos normalmente com o ` blockHash`. Para imprimi-los como uma string, precisamos usar o `blockHash.String()`.
### Executando Nosso Código
Podemos baixar o código completo do [diretório src](../src/18_1_blockinfo.go).
Podemos então, executar:
```
$ go run blockinfo.go
1830868
00000000000002d53b6b9bba4d4e7dc44a79cebd1024d1bcfb9b3cc07d6cad9c
```
O último número do bloco, junto com nosso hash, devem ser impressos.
## Procurando por Fundos
Devido às limitações do `btcd` no `rpcclient`, não podemos fazer uso da função `getwalletinfo`. No entanto, podemos usar o RPC `getbalance`:
```
wallet, err := client.GetBalance("*")
if err != nil {
log.Fatal(err)
}
fmt.Println(wallet)
```
O `client.GetBalance("*")` requer a entrada `"*"` devido a uma peculiaridade do `btcd`. O asterisco significa que desejamos obter o saldo de todas as nossas carteiras.
Se executarmos [o código src](../src/18_1_getbalance.go), deveremos obter uma saída semelhante a esta:
```
$ go run getbalance.go
0.000689 BTC
```
## Criando um Endereço
Podemos gerar endereços em Go, mas não podemos especificar o tipo do endereço:
Isso requer o uso de uma função especial `chaincfg`, para especificar para qual rede os endereços estão sendo criados. Esta especificação é necessária apenas durante a geração do endereço, por isso é usada apenas neste exemplo. Também podemos incluir isso nos demais exemplos, mas não é necessário.
Certifique-se de importar o `"github.com/btcsuite/btcd/chaincfg"`:
```
import (
"log"
"fmt"
"github.com/btcsuite/btcd/rpcclient"
"github.com/btcsuite/btcd/chaincfg"
)
```
Em seguida, vamos chamar o `connCfG` com o parâmetro `chaincfg.TestNet3Params.Name`:
```
connCfg := &rpcclient.ConnConfig{
Host: "localhost:18332",
User: "bitcoinrpc",
Pass: "431451790e3eee1913115b9dd2fbf0ac",
HTTPPostMode: true,
DisableTLS: true,
Params: chaincfg.TestNet3Params.Name,
}
client, err := rpcclient.New(connCfg, nil)
if err != nil {
log.Fatal(err)
}
defer client.Shutdown()
```
> **MAINNET VS TESTNET:** O `Params: chaincfg.TestNet3Params.Name` deve ser `Params: chaincfg.MainNetParams.Name,` na Mainnet.
Podemos então criar nosso endereço:
```
address, err := client.GetNewAddress("")
if err != nil {
log.Fatal(err)
}
fmt.Println(address)
```
Uma peculiaridade com o `client.GetNewAddress("")` é que uma string vazia precisa ser incluída para que tudo funcione perfeitamente.
Executando o [código fonte](18_1_getaddress.go) teremos os seguintes resultados:
```
$ go run getaddress.go
tb1qutkcj34pw0aq7n9wgp3ktmz780szlycwddfmza
```
### Decodificando um Endereço
Criar um endereço exigia um trabalho extra, em especificar a blockchain correta. Usar um endereço também exigirá, porque teremos que decodificá-lo antes de usá-lo.
Isso significa que teremos que importar as bibliotecas `"github.com/btcsuite/btcutil"` e `"github.com/btcsuite/btcd/chaincfg"`.
* O `btcutil` permite que um endereço Bitcoin seja decodificado de uma forma que o `rpcclient` possa entender. Isso é necessário ao trabalhar com endereços no `rpcclient`;
* O `chaincfg` é (novamente) usado para configurar nossa chain como a chain Testnet. Isso é necessário para a decodificação de endereços, pois os endereços usados na Mainnet e na Testnet são diferentes.
```
import (
"log"
"fmt"
"github.com/btcsuite/btcd/rpcclient"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcd/chaincfg"
)
```
A variável defaultNet agora é usada para especificar se nosso node Bitcoin está na Testnet ou na Mainnet. Essa informação (e o objeto `btcutil`) é então usada para decodificar o endereço.
> **MAINNET VS TESTNET:** `&chaincfg.TestNet3Params` deve ser `& chaincfg.MainNetParams` na Mainnet.
```
defaultNet := &chaincfg.TestNet3Params
addr, err := btcutil.DecodeAddress("mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha", defaultNet)
if err != nil {
log.Fatal(err)
}
```
> **NOTA:** Precisamos alterar o endereço (`mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha`) para um que seja da nossa carteira. Podemos usar o `bitcoin-cli listunspent` para encontrar alguns endereços com fundos para teste. Se quisermos ser realmente sofisticados, podemos modificar o código Go para obter um argumento e, em seguida, escrever um script que executa o `listunspent`, para depois salvarmos a informação em uma variável e executar o código Go nela.
Só depois disso usamos o RPC `getreceivedbyaddress` no nosso endereço decodificado:
```
wallet, err := client.GetReceivedByAddress(addr)
if err != nil {
log.Fatal(err)
}
fmt.Println(wallet)
```
Ao executar [o código](../src/18_1_getamountreceived.go), devemos obter uma saída semelhante a esta:
```
$ go run getamountreceived.go
0.0085 BTC
```
## Enviando uma Transação
Agora temos todas as peças do quebra-cabeça no lugar para enviar uma transação. Vamos querer:
1. Importar as bibliotecas corretas, incluindo a `chaincfg` para especificar uma rede e o `btcutil` para decodificar um endereço;
2. Escolher um endereço para enviar;
3. Decodificar esse endereço;
4. Executar o `sendtoaddress` para enviar fundos da maneira fácil.
```
package main
import (
"log"
"fmt"
"github.com/btcsuite/btcd/rpcclient"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcd/chaincfg"
)
func main() {
connCfg := &rpcclient.ConnConfig{
Host: "localhost:18332",
User: "StandUp",
Pass: "431451790e3eee1913115b9dd2fbf0ac",
HTTPPostMode: true,
DisableTLS: true,
}
client, err := rpcclient.New(connCfg, nil)
if err != nil {
log.Fatal(err)
}
defer client.Shutdown()
defaultNet := &chaincfg.TestNet3Params
addr, err := btcutil.DecodeAddress("n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi", defaultNet)
if err != nil {
log.Fatal(err)
}
sent, err := client.SendToAddress(addr, btcutil.Amount(1e4))
if err != nil {
log.Fatal(err)
}
fmt.Println(sent)
}
```
Quando executamos [o código](../src/18_1_sendtransaction.go), o txid da transação nos será retornado:
```
$ go run sendtransaction.go
9aa4cd6559e0d69059eae142c35bfe78b71a8084e1fcc2c74e2a9675e9e7489d
```
### Consultando uma Transação
Para consultar uma transação, como a que acabamos de enviar, precisaremos fazer mais uma vez algumas conversões, desta vez do txid. O `"github.com/btcsuite/btcd/chaincfg/chainhash"` é importado para permitir que os hashes sejam armazenados no código Go. O `chainhash.NewHashFromStr("hash")` converte um hash em uma string para um formato que funciona com o rpcclient.
```
package main
import (
"log"
"fmt"
"github.com/btcsuite/btcd/rpcclient"
"github.com/btcsuite/btcd/chaincfg/chainhash"
)
func main() {
connCfg := &rpcclient.ConnConfig{
Host: "localhost:18332",
User: "StandUp",
Pass: "431451790e3eee1913115b9dd2fbf0ac",
HTTPPostMode: true,
DisableTLS: true,
}
client, err := rpcclient.New(connCfg, nil)
if err != nil {
log.Fatal(err)
}
defer client.Shutdown()
chash, err := chainhash.NewHashFromStr("1661ce322c128e053b8ea8fcc22d17df680d2052983980e2281d692b9b4ab7df")
if err != nil {
log.Fatal(err)
}
transactions, err := client.GetTransaction(chash)
if err != nil {
log.Fatal(err)
}
fmt.Println(transactions)
}
```
> **NOTA:** Novamente, vamos querer trocar o txid por um que realmente será reconhecido pelo nosso sistema.
Ao executar [o código](../src/18_1_lookuptransaction.go), ele imprimirá os detalhes associados a uma transação, como seu valor e quantas vezes foi confirmada:
```
$ go run lookuptransaction.go
{
"amount": 0.00100000,
"confirmations": 4817,
"blockhash": "000000006628870b0a8a66abea9cf0d4e815c491f079e3fa9e658a87b5dc863a",
"blockindex": 117,
"blocktime": 1591857418,
"txid": "1661ce322c128e053b8ea8fcc22d17df680d2052983980e2281d692b9b4ab7df",
"walletconflicts": [
],
"time": 1591857343,
"timereceived": 1591857343,
"bip125-replaceable": "no",
"details": [
{
"address": "mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha",
"category": "receive",
"amount": 0.00100000,
"label": "",
"vout": 0
}
],
"hex": "02000000000101e9e8c3bd057d54e73baadc60c166860163b0e7aa60cab33a03e89fb44321f8d5010000001716001435c2aa3fc09ea53c3e23925c5b2e93b9119b2568feffffff02a0860100000000001976a914600c8c6a4abb0a502ea4de01681fe4fa1ca7800688ac65ec1c000000000017a91425b920efb2fde1a0277d3df11d0fd7249e17cf8587024730440220403a863d312946aae3f3ef0a57206197bc67f71536fb5f4b9ca71a7e226b6dc50220329646cf786cfef79d60de3ef54f702ab1073694022f0618731902d926918c3e012103e6feac9d7a8ad1ac6b36fb4c91c1c9f7fff1e7f63f0340e5253a0e4478b7b13f41fd1a00"
}
```
## Resumo: Acessando o Bitcoind com Go
Embora o `btcd` e o `rpcclient` tenham alguns limites, ainda podemos executar os principais comandos RPC no Go. A documentação para o `rpcclient` está disponível no [Godoc](https://godoc.org/github.com/btcsuite/btcd/rpcclient). Se a documentação não tiver o que procuramos, podemos consultar também o [repositório btcd](https://github.com/btcsuite/btcd). Geralmente é bem documentado e fácil de ler. Com base nesses exemplos, devemos ser capazes de incorporar o Bitcoin em um projeto Go e fazer coisas como enviar e receber moedas.
## O Que Vem Depois?
Vamos aprender mais sobre "Conversando com o Bitcoind com Outras Linguagens" na seção [§18.2: Acessando o Bitcoin com Java](18_2_Accessing_Bitcoind_with_Java.md).

View File

@ -0,0 +1,332 @@
# 18.2: Acessando o Bitcoind com Java
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Esta seção explica como interagir com `bitcoind` usando a linguagem de programação Java e o [JavaBitcoindRpcClient](https://github.com/Polve/JavaBitcoindRpcClient).
## Configurando o Java
Podemos instalar o Java em nosso servidor, usando o comando `apt-get`. Também precisaremos instalar o [Apache Maven](http://maven.apache.org/) para gerenciar as dependências.
```
$ sudo apt-get install openjdk-11-jre-headless maven
```
Podemos verificar a instalação do Java usando o comando abaixo:
```
$ java -version
openjdk version "11.0.8" 2020-07-14
OpenJDK Runtime Environment (build 11.0.8+10-post-Debian-1deb10u1)
OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Debian-1deb10u1, mixed mode, sharing)
```
### Criando um Projeto Maven
Para programar o Bitcoin usando o java, criaremos um projeto Maven:
```
$ mvn archetype:generate -DgroupId=com.blockchaincommons.lbtc -DartifactId=java-project -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
```
Isso irá baixar algumas dependências:
```
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom (4 KB at 4.2 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-plugins/22/maven-plugins-22.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-plugins/22/maven-plugins-22.pom (13 KB at 385.9 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/maven-parent/21/maven-parent-21.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/maven-parent/21/maven-parent-21.pom (26 KB at 559.6 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/apache/apache/10/apache-10.pom
..............
```
Ele também criará um arquivo de configuração `pom.xml`:
```
$ cd java-project
$ ls -lagh
total 16K
drwxr-xr-x 3 sudo 4.0K Sep 1 13:58 .
drwxr-xr-x 15 sudo 4.0K Sep 1 13:58 ..
-rw-r--r-- 1 sudo 663 Sep 1 13:58 pom.xml
drwxr-xr-x 4 sudo 4.0K Sep 1 13:58 src
```
Para incluir o `JavaBitcoindRpcClient`, devemos adicionar nossa dependência a `<dependendencies>` no arquivo `pom.xml`.
```xml
<dependency>
<groupId>wf.bitcoin</groupId>
<artifactId>bitcoin-rpc-client</artifactId>
<version>1.2.1</version>
</dependency>
```
Também precisamos adicionar propriedades do compilador para indicar qual versão do JDK compilará o código-fonte.
```
<properties>
<!-- https://maven.apache.org/general.html#encoding-warning -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
```
Sempre que adicionarmos um código-fonte às nossas classes, poderemos testá-lo com:
```
$ mvn compile
```
Também podemos executá-lo com `exec: java`
```
$ mvn exec:java -Dexec.mainClass=com.blockchaincommons.lbtc.App
```
### Criando Projetos Alternativos
Se usarmos o [Gradle](https://gradle.org/releases/), poderemos executar o seguinte comando:
```groovy
compile 'wf.bitcoin:JavaBitcoindRpcClient:1.2.1'
```
Se quisermos um projeto de amostra e algumas instruções sobre como executá-lo no servidor que acabamos de criar, podemos consultar o [Projeto de amostra do Bitcoind Java](https://github.com/bvolpato/bitcoind-java-client-sample). Também podemos navegar por todo o código de origem do [bitcoin-rpc-client](https://github.com/Polve/bitcoin-rpc-client).
## Construindo Nossa Conexão
Para usar o `JavaBitcoindRpcClient`, precisamos criar uma instância `BitcoindRpcClient`. Fazemos isso criando um URL com argumentos de nome de usuário, senha, endereço IP e porta. Como devemos nos lembrar, o endereço IP `127.0.0.1` e a porta `18332` devem estar corretos para a configuração testnet padrão descrita neste curso, enquanto podemos extrair o usuário e a senha abrindo o arquivo `~/.bitcoin/bitcoin.conf`.
```java
BitcoindRpcClient rpcClient = new BitcoinJSONRPCClient("http://StandUp:6305f1b2dbb3bc5a16cd0f4aac7e1eba@localhost:18332");
```
Podemos observar que também precisaremos importar as informações apropriadas:
```
import wf.bitcoin.javabitcoindrpcclient.BitcoinJSONRPCClient;
import wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient;
```
> **MAINNET VS TESTNET:** A porta seria 8332 para uma configuração da mainnet.
Se o `rpcClient` for inicializado com sucesso, poderemos enviar comandos RPC.
Mais tarde, quando terminarmos nossa conexão `bitcoind`, precisaremos fechá-la:
```
rpcClient.stop();
```
### Fazendo uma Chamada RPC
Você verá que o `BitcoindRpcClient` fornece a maioria das funcionalidades que podem ser acessadas através do `bitcoin-cli` ou outros métodos RPC, usando o mesmo método que o nome, mas em camelCase.
Por exemplo, para executar o comando `getmininginfo` para obter as informações do bloco e a dificuldade na rede, devemos usar o método `getMiningInfo()`:
```java
MiningInfo info = rpcClient.getMiningInfo();
System.out.println("Mining Information");
System.out.println("------------------");
System.out.println("Chain......: " + info.chain());
System.out.println("Blocks.....: " + info.blocks());
System.out.println("Difficulty.: " + info.difficulty());
System.out.println("Hash Power.: " + info.networkHashps());
```
O retorno para esta linha deve algo próximo a isso:
```
Mining Information
------------------
Chain......: test
Blocks.....: 1830905
Difficulty.: 4194304
Hash Power.: 40367401348837.41
```
### Fazendo uma Chamada RPC com Argumentos
Podemos procurar os endereços em nossa carteira passando o endereço como um argumento para o comando `getAddressInfo`:
```java
String addr1 = "mvLyH7Rs45c16FG2dfV7uuTKV6pL92kWxo";
AddressInfo addr1Info = rpcClient.getAddressInfo(addr1);
System.out.println("Address: " + addr1Info.address());
System.out.println("MasterFingerPrint: " + addr1Info.hdMasterFingerprint());
System.out.println("HdKeyPath: " + addr1Info.hdKeyPath());
System.out.println("PubKey: " + addr1Info.pubKey());
```
O resultado será mais ou menos assim:
```
Address: mvLyH7Rs45c16FG2dfV7uuTKV6pL92kWxo
MasterFingerPrint: ce0c7e14
HdKeyPath: m/0'/0'/5'
PubKey: 0368d0fffa651783524f8b934d24d03b32bf8ff2c0808943a556b3d74b2e5c7d65
```
### Executando Nosso Código
O código para esses exemplos pode ser encontrado no [diretório src/](../src/18_2_App-getinfo.java) e deve ser instalado na estrutura de diretório padrão criada neste caso como `~/java-project/src/main/java/com/blockchaincommons/lbtc/App.java`. Ele pode então ser compilado e executado.
```
$ mvn compile
$ mvn exec:java -Dexec.mainClass=com.blockchaincommons.lbtc.App
Chain......: test
Blocks.....: 1831079
Difficulty.: 4194304
Hash Power.: 38112849943221.16
Address: mvLyH7Rs45c16FG2dfV7uuTKV6pL92kWxo
MasterFingerPrint: ce0c7e14
HdKeyPath: m/0'/0'/5'
PubKey: 0368d0fffa651783524f8b934d24d03b32bf8ff2c0808943a556b3d74b2e5c7d65
```
Você também verá muito mais informações sobre a compilação, é claro.
## Consultando Fundos
Recuperar o saldo de uma conta inteira é tão fácil quanto:
```
System.out.println("Balance: " + rpcClient.getBalance());
```
## Criando um Endereço
Podemos criar um novo endereço em nossa carteira, anexando um rótulo específico a ela e até mesmo descartando nossa chave privada.
```java
String address = rpcClient.getNewAddress("Learning-Bitcoin-from-the-Command-Line");
System.out.println("New Address: " + address);
String privKey = rpcClient.dumpPrivKey(address);
System.out.println("Priv Key: " + privKey);
```
Retorno:
```
New Address: mpsFtZ8qTJPRGZy1gaaUw37fHeUSPLkzzs
Priv Key: cTy2AnmAALsHokYzJzTdsUBSqBtypmWfmSNYgG6qQH43euUZgqic
```
## Enviando uma Transação
A biblioteca `JavaBitcoindRpcClient` possui algumas ferramentas interessantes que facilitam a criação de uma transação desde o início.
### Criando uma Transação
Podemos criar uma transação bruta usando o método `createRawTransaction`, passando como argumentos dois objetos ArrayList contendo entradas e saídas a serem utilizadas.
Primeiro configuramos nossos novos endereços, aqui um endereço existente em nosso sistema e um novo endereço.
```
String addr1 = "tb1qdqkc3430rexxlgnma6p7clly33s6jjgay5q8np";
System.out.println("Used address addr1: " + addr1);
String addr2 = rpcClient.getNewAddress();
System.out.println("Created address addr2: " + addr2);
```
Então, podemos usar o RPC `listUnspent` para encontrar UTXOs para o endereço existente.
```
List<Unspent> utxos = rpcClient.listUnspent(0, Integer.MAX_VALUE, addr1);
System.out.println("Found " + utxos.size() + " UTXOs (unspent transaction outputs) belonging to addr1");
```
Aqui está um resultado de todas as informações:
```java
System.out.println("Created address addr1: " + addr1);
String addr2 = rpcClient.getNewAddress();
System.out.println("Created address addr2: " + addr2);
List<String> generatedBlocksHashes = rpcClient.generateToAddress(110, addr1);
System.out.println("Generated " + generatedBlocksHashes.size() + " blocks for addr1");
List<Unspent> utxos = rpcClient.listUnspent(0, Integer.MAX_VALUE, addr1);
System.out.println("Found " + utxos.size() + " UTXOs (unspent transaction outputs) belonging to addr1");
```
As transações são criadas com o comando `BitcoinRawTxBuilder`:
```
BitcoinRawTxBuilder txb = new BitcoinRawTxBuilder(rpcClient);
```
Primeiro preenchemos as entradas com os UTXOs que estamos gastando:
```
TxInput in = utxos.get(0);
txb.in(in);
```
> :warning: **AVISO:** Obviamente, em um programa real, selecionaríamos um UTXO de forma inteligente, porém, neste caso, pegamos apenas o enésimo, uma tática que usaremos ao longo deste capítulo.
Em segundo lugar, preenchemos as saídas, cada uma com um valor e um endereço:
```
BigDecimal estimatedFee = BigDecimal.valueOf(0.00000200);
BigDecimal txToAddr2Amount = utxos.get(0).amount().subtract(estimatedFee);
txb.out(addr2, txToAddr2Amount);
System.out.println("unsignedRawTx in amount: " + utxos.get(0).amount());
System.out.println("unsignedRawTx out amount: " + txToAddr2Amount);
```
Agora estamos prontos para realmente criar a transação:
```
String unsignedRawTxHex = txb.create();
System.out.println("Created unsignedRawTx from addr1 to addr2: " + unsignedRawTxHex);
```
### Assinando uma Transação
Agora podemos assinar a transação com o método `signRawTransactionWithKey`. Este método recebe como parâmetros uma transação de string bruta não assinada, a chave privada do endereço de envio e o objeto TxInput.
```java
SignedRawTransaction srTx = rpcClient.signRawTransactionWithKey(
unsignedRawTxHex,
Arrays.asList(rpcClient.dumpPrivKey(addr1)), //
Arrays.asList(in),
null);
System.out.println("signedRawTx hex: " + srTx.hex());
System.out.println("signedRawTx complete: " + srTx.complete());
```
### Enviando uma Transação
Finalmente, o envio requer o comando `sendRawTransaction`:
```java
String sentRawTransactionID = rpcClient.sendRawTransaction(srTx.hex());
System.out.println("Sent signedRawTx (txID): " + sentRawTransactionID);
```
### Executando Nosso Código
Agora podemos executar [o código da transação](../src/18_2_App-sendtx.java) como `~/java-project/src/main/java/com/blockchaincommons/lbtc/App.java`.
```
$ mvn compile
$ mvn exec:java -Dexec.mainClass=com.blockchaincommons.lbtc.App
Used address addr1: tb1qdqkc3430rexxlgnma6p7clly33s6jjgay5q8np
Created address addr2: tb1q04q2wzlhfqlrnz95ynfj7gp4t3yynrj0542smv
Found 1 UTXOs (unspent transaction outputs) belonging to addr1
unsignedRawTx in amount: 0.00850000
unsignedRawTx out amount: 0.00849800
Created unsignedRawTx from addr1 to addr2: 0200000001d2a90fc3b43e8eb4ae9452af43c9448112d359cac701f7f537aa8b6f39193bb90100000000ffffffff0188f70c00000000001600147d40a70bf7483e3988b424d32f20355c48498e4f00000000
signedRawTx hex: 02000000000101d2a90fc3b43e8eb4ae9452af43c9448112d359cac701f7f537aa8b6f39193bb90100000000ffffffff0188f70c00000000001600147d40a70bf7483e3988b424d32f20355c48498e4f024730440220495fb64d8cf9dee9daa8535b8867709ac8d3763d693fd8c9111ce610645c76c90220286f39a626a940c3d9f8614524d67dd6594d9ee93818927df4698c1c8b8f622d01210333877967ac52c0d0ec96aca446ceb3f51863de906e702584cc4da2780d360aae00000000
signedRawTx complete: true
Sent signedRawTx (txID): 82032c07e0ed91780c3369a1943ea8abf49c9e11855ffedd935374ecbc789c45
```
## Escutando Transações ou Blocos
Tal como acontece com [C e suas bibliotecas ZMQ](16_3_Receiving_Bitcoind_Notifications_with_C.md), existem maneiras fáceis de usar o Java para escutar a blockchain, além de executar o código específico quando algo acontece, como uma transação que envolve um endereço em nossa carteira, ou até a geração de um novo bloco na rede.
Para fazer isso, podemos usar a classe `BitcoinAcceptor` do `JavaBitcoindRpcClient`, que nos permite anexar "ouvintes" à rede.
```java
String blockHash = rpcClient.getBestBlockHash();
BitcoinAcceptor acceptor = new BitcoinAcceptor(rpcClient, blockHash, 6, new BitcoinPaymentListener() {
@Override
public void transaction(Transaction tx) {
System.out.println("Transaction: " + tx);
}
@Override
public void block(String block) {
System.out.println("Block: " + block);
}
});
acceptor.run();
```
Veja [o diretório src/](../src/18_2_App-listen.java) para o código completo. Cada vez que uma transação é enviada ou um novo bloco é gerado, devemos ver a saída em nosso console:
```
Transaction: {account=Tests, address=mhopuJzgmTwhGfpNLCJ9CRknugY691oXp1, category=receive, amount=5.0E-4, label=Tests, vout=1, confirmations=0, trusted=false, txid=361e8fcff243b74ebf396e595a007636654f67c3c7b55fd2860a3d37772155eb, walletconflicts=[], time=1513132887, timereceived=1513132887, bip125-replaceable=unknown}
Block: 000000004564adfee3738314549f7ca35d96c4da0afc6b232183917086b6d971
```
### Resumo: Acessando o Bitcoind com Java
Usando a biblioteca `javabitcoinrpc`, podemos acessar facilmente o `bitcoind` por meio de chamadas RPC com Java. Também teremos acesso a recursos adicionais interessantes, como o serviço de escuta usando o comando `bitcoinAcceptor`.
## O Que Vem Depois?
Vamos aprender mais sobre "Conversando com o Bitcoind com Outras Linguagens" na seção [§18.3: Acessando o Bitcoind com NodeJS](18_3_Accessing_Bitcoind_with_NodeJS.md).

View File

@ -0,0 +1,273 @@
# 18.3: Acessando o Bitcoind com NodeJS
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Esta seção explica como interagir com o `bitcoind` usando a linguagem de programação NodeJS e o [pacote BCRPC](https://github.com/dgarage/bcrpc).
## Configurando o Node.js
O BCRPC é construído em node.js. Portanto, primeiro precisamos instalar os pacotes `node.js` e o `npm` (o gerenciador de pacotes do node) em nosso sistema.
Se estiver usando uma máquina Ubuntu, podemos executar os seguintes comandos para obter uma nova versão do `node.js`, ao invés da versão terrivelmente desatualizada no sistema de pacotes do Ubuntu.
```
$ curl -sL https://deb.nodesource.com/setup_14.x | sudo bash -
$ sudo apt-get install -y nodejs
$ sudo npm install mocha -g
```
### Configurando o BCRPC
Agora podemos clonar o pacote BCRPC do GitHub e instalar as dependências.
```
$ git clone https://github.com/dgarage/bcrpc.git
$ cd bcrpc
$ npm install
```
Para testar o pacote BCRPC, devemos primeiro definir as variáveis de ambiente para o rpcuser e rpcpassword. Como de costume, elas vêm do `~/.bitcoin/bitcoin.conf`. Também devemos definir a porta RPC como sendo 18332, que deve ser a correta para a configuração Testnet padrão descrita nos documentos.
```
$ export BITCOIND_USER=StandUp
$ export BITCOIND_PASS=d8340efbcd34e312044c8431c59c792c
$ export BITCOIND_PORT=18332
```
> :warning: **AVISO:** Obviamente, você nunca colocaria sua senha em uma variável de ambiente em um ambiente de produção.
> :link: **MAINNET VS TESTNET:** A porta seria 8332 para uma configuração na Mainnet.
Agora podemos verificar se tudo está funcionando corretamente:
```
$ npm test
> bcrpc@0.2.2 test /home/user1/bcrpc
> mocha tests.js
BitcoinD
✓ is running
bcrpc
✓ can get info
2 passing (36ms)
```
Parabéns, agora temos um wrapper RPC pronto para ser usado no Bitcoin com o Node.js e que está funcionando com as nossas configurações do Bitcoin.
### Criando um Projeto BCRPC
Agora podemos criar um novo projeto Node.js e instalar o BCRPC via npm.
```
$ cd ~
$ mkdir myproject
$ cd myproject
$ npm init
[continue with default options]
$ npm install bcrpc
```
## Construindo Nossa Conexão
Em nosso diretório `myproject`, criamos um arquivo `.js` onde nosso código JavaScript será executado.
Podemos iniciar uma conexão RPC criando um `RpcAgent`:
```
const RpcAgent = require('bcrpc');
agent = new RpcAgent({port: 18332, user: 'StandUp', pass: 'd8340efbcd34e312044c8431c59c792c'});
```
Obviamente, nosso `user` e `pass` devem coincidir novamente com o que está em nosso `~/.bitcoin/bitcoin.conf`, e usamos a `port 18332` se estivermos na Testnet.
### Fazendo uma chamada RPC
Usando o BCRPC, podemos usar os mesmos comandos RPC que normalmente usaríamos via `bitcoin-cli` com nosso `RpcAgent`, exceto que eles precisam estar em camelCase. Por exemplo, `getblockhash` seria `getBlockHash`.
Para imprimir o número do bloco mais recente, basta chamar o `getBlockCount` através do nosso `RpcAgent`:
```
agent.getBlockCount(function (err, blockCount) {
if (err)
throw Error(JSON.stringify(err));
console.log(blockCount.result);
});
```
### Fazendo uma chamada RPC com argumentos
As funções BCRPC podem aceitar argumentos. Por exemplo, o `getBlockHash` recebe o `blockCount.result` como uma entrada.
```
agent.getBlockHash(blockCount.result, function (err, hash) {
if (err)
throw Error(JSON.stringify(err));
console.log(hash.result);
})
```
O resultado das funções BCRPC é um objeto JSON contendo informações sobre quaisquer erros e o id da solicitação. Ao acessar nosso resultado, adicionamos o `.result` no final dele para especificar que estamos interessados no resultado real, não em informações sobre os erros.
### Executando Nosso Código
Podemos encontrar o código `getinfo` no [diretório src/](../src/18_3_getinfo.js).
```
$ node getinfo.js
1831094
00000000000002bf8b522a830180ad3a93b8eed33121f54b3842d8838580a53c
```
Isso é com o que a saída do exemplo acima se pareceria se substituíssemos o `console.log(blockCount.result);` e o `console.log(hash.result);` por `console.log(blockCount);` e `console.log (hash);`, respectivamente:
```
{ result: 1774686, error: null, id: null }
{
result: '00000000000000d980c495a2b7addf09bb0a9c78b5b199c8e965ee54753fa5da',
error: null,
id: null
}
```
## Pesquisando por Fundos
É útil, ao aceitar Bitcoin, verificar o Bitcoin recebido em um endereço específico em nossa carteira. Por exemplo, se administrássemos uma loja online que aceita Bitcoin, para cada pagamento de um cliente, geraríamos um novo endereço, mostraríamos esse endereço ao cliente e, em seguida, verificaríamos o saldo do endereço após algum tempo, para certificar-se de que o montante foi recebido:
```
agent.getReceivedByAddress('mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha', function (err, addressInfo) {
if (err)
throw Error(JSON.stringify(err));
console.log(addressInfo.result);
});
```
> :information_source: **NOTA:** Obviamente, precisaremos inserir um endereço reconhecido por nossa máquina.
Por padrão, esta função verifica as transações que foram confirmadas uma vez, no entanto, podemos aumentar para um número maior, como 6:
```
agent.getReceivedByAddress('mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha', 6, function (err, addressInfo) {
if (err)
throw Error(JSON.stringify(err));
console.log(addressInfo.result);
});
```
### Pesquisando Informações da Carteira
Também podemos procurar informações adicionais sobre nossa carteira e visualizar nosso saldo, contagem de transações etc.
```
agent.getWalletInfo(function (err, walletInfo) {
if (err)
throw Error(JSON.stringify(err));
console.log(walletInfo.result);
});
```
O código está disponível como [walletinfo.js](../src/18_3_walletinfo.js).
```
$ node walletinfo.js
0.008498
{
walletname: '',
walletversion: 169900,
balance: 0.010438,
unconfirmed_balance: 0,
immature_balance: 0,
txcount: 4,
keypoololdest: 1596567843,
keypoolsize: 999,
hdseedid: 'da5a1b058deb9e51ecffef1b0ddc069a5dfb2c5f',
keypoolsize_hd_internal: 1000,
paytxfee: 0,
private_keys_enabled: true,
avoid_reuse: false,
scanning: false
}
```
Ao invés de imprimirmos todos os detalhes associados à nossa carteira, podemos imprimir informações específicas, como nosso saldo. Como um objeto JSON está sendo acessado, podemos fazer isso alterando a linha `console.log(walletInfo.result);` para `console.log(walletInfo.result.balance);`:
## Criando um Endereço
Também podemos passar argumentos adicionais para os comandos RPC. Por exemplo, o seguinte gera um novo endereço legado, com o sinalizador `-addresstype`.
```
agent.getNewAddress('-addresstype', 'legacy', function (err, newAddress) {
if (err)
throw Error(JSON.stringify(err));
console.log(newAddress.result);
});
```
Isso é o mesmo que executar o seguinte na linha de comando:
```
$ bitcoin-cli getnewaddress -addresstype legacy
mtGPcBvRPZFEHo2YX8un9qqPBydhG82uuZ
```
No BCRPC, geralmente podemos usar os mesmos sinalizadores que no `bitcoin-cli` no BCRPC. Embora usamos o camelCase (`getNewAddress`) para os métodos, os sinalizadores, que normalmente são separados por espaços na linha de comando, são colocados em strings e separados por vírgulas.
## Enviando uma Transação
Podemos enviar saldos para um endereço muito facilmente, usando a função `sendToAddress`:
```
agent.sendToAddress(newAddress.result, 0.00001, function(err, txid) {
if (err)
throw Error(JSON.stringify(err));
console.log(txid.result);
});
```
Isso deve retornar o txid da transação:
```
1679bee019c61608340b79810377be2798efd4d2ec3ace0f00a1967af70666b9
```
### Pesquisando uma Transação
Agora podemos desejar visualizar uma transação, como a que acabamos de enviar.
```
agent.getTransaction(txid.result, function (err, transaction) {
if (err)
throw Error(JSON.stringify(err));
console.log(transaction.result);
});
```
Devemos obter uma saída semelhante a esta:
```
{
amount: 0.001,
confirmations: 4776,
blockhash: '000000006628870b0a8a66abea9cf0d4e815c491f079e3fa9e658a87b5dc863a',
blockindex: 117,
blocktime: 1591857418,
txid: '1661ce322c128e053b8ea8fcc22d17df680d2052983980e2281d692b9b4ab7df',
walletconflicts: [],
time: 1591857343,
timereceived: 1591857343,
'bip125-replaceable': 'no',
details: [
{
address: 'mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha',
category: 'receive',
amount: 0.001,
label: '',
vout: 0
}
],
hex: '02000000000101e9e8c3bd057d54e73baadc60c166860163b0e7aa60cab33a03e89fb44321f8d5010000001716001435c2aa3fc09ea53c3e23925c5b2e93b9119b2568feffffff02a0860100000000001976a914600c8c6a4abb0a502ea4de01681fe4fa1ca7800688ac65ec1c000000000017a91425b920efb2fde1a0277d3df11d0fd7249e17cf8587024730440220403a863d312946aae3f3ef0a57206197bc67f71536fb5f4b9ca71a7e226b6dc50220329646cf786cfef79d60de3ef54f702ab1073694022f0618731902d926918c3e012103e6feac9d7a8ad1ac6b36fb4c91c1c9f7fff1e7f63f0340e5253a0e4478b7b13f41fd1a00'
}
```
O código completo está disponível no [sendtx.js](../src/18_3_sendtx.js).
## Resumo: Acessando o Bitcoind com NodeJS
Com o BCRPC podemos acessar todos os comandos RPC disponíveis através do `bitcoin-cli`, usando o JavaScript. O [BCRPC README](https://github.com/dgarage/bcrpc) tem alguns exemplos que usam promises (os exemplos neste livro usam callbacks). O [JavaScript por trás dele](https://github.com/dgarage/bcrpc/blob/master/index.js) é curto e bem legível.
Com base nesses exemplos, devemos ser capazes de incorporar Bitcoin em um projeto Node.js e fazer coisas como enviar e receber fundos.
## O Que Vem Depois?
Vamos aprender mais sobre "Conversando com o Bitcoind com Outras Linguagens" na seção [§18.4: Acessando o Bitcoind com Python](18_4_Accessing_Bitcoind_with_Python.md).

View File

@ -0,0 +1,495 @@
# 18.4: Acessando o Bitcoind com Python
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Esta seção explica como interagir com o `bitcoind` usando a linguagem de programação Python e o [Python-BitcoinRPC](https://github.com/jgarzik/python-bitcoinrpc).
## Configurando o Python
Se já temos o Bitcoin Core instalado, provavelmente temos o Python 3 disponível.
Podemos verificar isso executando:
```$ python3 --version```
Se ele retornar um número de versão (por exemplo, `3.7.3` ou `3.8.3`), então temos o python3 instalado.
No entanto, se não tivermos o Python instalado, precisaremos compilá-lo a partir do código-fonte. Devemos consultar como fazer isso em ["Construindo Python da Fonte"](18_4_Accessing_Bitcoind_with_Python.md#variant-build-python-from-source) antes de continuarmos.
### Configurando o BitcoinRPC
Quer tenhamos usado um Python existente ou compilado a partir da fonte, agora estamos prontos para instalar a biblioteca `python-bitcoinrpc`:
```
$ pip3 install python-bitcoinrpc
```
Se não instalamos o `pip`, precisaremos executar o seguinte:
```
$ sudo apt install python3-pip
```
Em seguida, vamos repetir o comando `pip3 install python-bitcoinrpc`.
### Criando um Projeto BitcoinRPC
Geralmente, precisaremos incluir declarações apropriadas do `bitcoinrpc` em nosso projetos Bitcoin usando o Python. O seguinte fornecerá acesso aos comandos baseados em RPC:
```py
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
```
Também podemos achar o seguinte comando útil:
```py
from pprint import pprint
import logging
```
O `pprint` irá imprimir a resposta `json` do `bitcoind`.
O `logging` irá imprimir a chamada que fizemos para o respose do `bitcoind` e o próprio `bitcoind`, o que é útil quando fazemos um monte de chamadas juntas. Se não quisermos um retorno muito grande no terminal, podemos comentar o bloco `logging`.
## Construindo a Nossa Conexão
Agora estamos prontos para começar a interagir com o `bitcoind` estabelecendo uma conexão. Vamos criar um arquivo chamado `btcrpc.py` e digitar o seguinte:
```py
logging.basicConfig()
logging.getLogger("BitcoinRPC").setLevel(logging.DEBUG)
# rpc_user e rpc_password estão configurados no arquivo bitcoin.conf
rpc_user = "StandUp"
rpc_pass = "6305f1b2dbb3bc5a16cd0f4aac7e1eba"
rpc_host = "127.0.0.1"
rpc_client = AuthServiceProxy(f"http://{rpc_user}:{rpc_pass}@{rpc_host}:18332", timeout=120)
```
Os argumentos na URL são `<rpc_username>:<rpc_password>@<host_IP_address>:<port>`. Como de costume, o `user` e o `pass` são encontrados no arquivo `~/.bitcoin/bitcoin.conf`, enquanto o `host` é o nosso localhost, e a porta é `18332` para Testnet. O argumento `timeout` é especificado desde o tempo limite dos sockets sob grande demanda na rede principal. Se obtivermos a resposta `socket.timeout: timed out`, precisamos ser pacientes e aumentar o` timeout`.
> :link: **MAINNET VS TESTNET:** A porta seria 8332 para uma configuração na Mainnet.
### Fazendo uma Chamada RPC
Se o `rpc_client` for inicializado com sucesso, seremos capazes de enviar comandos RPC para o nosso node do Bitcoin.
Para usar um método RPC do `python-bitcoinrpc`, usaremos o objeto `rpc_client` que criamos, que fornece a maior parte da funcionalidade que pode ser acessada através do `bitcoin-cli`, usando os mesmos nomes do método.
Por exemplo, o comando a seguir irá recuperar a contagem de blocos do nosso node:
```py
block_count = rpc_client.getblockcount()
print("---------------------------------------------------------------")
print("Block Count:", block_count)
print("---------------------------------------------------------------\n")
```
Devemos obter a seguinte resposta com o `logging` habilitado:
```sh
DEBUG:BitcoinRPC:-3-> getblockcount []
DEBUG:BitcoinRPC:<-3- 1773020
---------------------------------------------------------------
Block Count: 1773020
---------------------------------------------------------------
```
### Fazendo uma Chamada RPC com Argumentos
Podemos usar esse blockcount como um argumento para recuperar o blockhash de um bloco e também para recuperar os detalhes do bloco.
Isso é feito enviando nossos comandos do objeto `rpc_client` com um argumento:
```py
blockhash = rpc_client.getblockhash(block_count)
block = rpc_client.getblock(blockhash)
```
O `getblockhash` retornará um único valor, enquanto o `getblock` retornará um array associativo de informações sobre o bloco, que inclui um array em `block['tx']` fornecendo detalhes sobre cada transação dentro do bloco:
```py
nTx = block['nTx']
if nTx > 10:
it_txs = 10
list_tx_heading = "First 10 transactions: "
else:
it_txs = nTx
list_tx_heading = f"All the {it_txs} transactions: "
print("---------------------------------------------------------------")
print("BLOCK: ", block_count)
print("-------------")
print("Block Hash...: ", blockhash)
print("Merkle Root..: ", block['merkleroot'])
print("Block Size...: ", block['size'])
print("Block Weight.: ", block['weight'])
print("Nonce........: ", block['nonce'])
print("Difficulty...: ", block['difficulty'])
print("Number of Tx.: ", nTx)
print(list_tx_heading)
print("---------------------")
i = 0
while i < it_txs:
print(i, ":", block['tx'][i])
i += 1
print("---------------------------------------------------------------\n")
```
### Executando nosso código
Podemos usar [o código que está no src/](../src/18_4_getinfo.py) e executá-lo com `python3`:
```
$ python3 getinfo.py
---------------------------------------------------------------
Block Count: 1831106
---------------------------------------------------------------
---------------------------------------------------------------
BLOCK: 1831106
-------------
Block Hash...: 00000000000003b2ea7c2cdfffd86156ad1f5606ab58e128940a2534d1348b04
Merkle Root..: 056a547fe59208167eef86fa694263728fb684119254b340c1f86bdd423a8082
Block Size...: 52079
Block Weight.: 128594
Nonce........: 1775583700
Difficulty...: 4194304
Number of Tx.: 155
First 10 transactions:
---------------------
0 : d228d55112e3aa26265b0118cfdc98345c229d20fe074b9afb87107c03ce11b5
1 : 92822e8e34fafb472b87c99ea3f3e16440452b3f361ed86c6fa62175173fb750
2 : fa7c67600c14d4aa350a9674688f1429577954f4a6c5e4639d06c8964824f647
3 : 3a91d1527e308e5603dafde7ab17824f441a73a779d2571d073466dc9e8451b2
4 : 30fd0e5527b1522e7b26a4818b9edac80fe47c0c39fc34705478a49e684708d0
5 : 24c5372b38c78cbaf5b0b305925502a491bc0c1b5758f50c0bd335abb6ae85f5
6 : be70e125a5793efc5e32051fecba0668df971bdf371138c8261201c2a46b2d38
7 : 41ebf52c847a59ba0aeb4425c74e89a01e91defa86a82785ff53ed4668054561
8 : dc8211b4ce122f87692e7c203672e3eb1ffc44c0a307eafcc560323fcc5fae78
9 : 59e2d8e11cad287eacf3207e64a373f65059286b803ef0981510193ae29cbc8c
---------------------------------------------------------------
```
## Pesquisando Fundos
Da mesma forma, podemos recuperar as informações da nossa carteira com o RPC `getwalletinfo`:
```py
wallet_info = rpc_client.getwalletinfo()
print("---------------------------------------------------------------")
print("Wallet Info:")
print("-----------")
pprint(wallet_info)
print("---------------------------------------------------------------\n")
```
Devemos obter um retorno semelhante ao que tivemos abaixo com o `logging` desabilitado:
```sh
---------------------------------------------------------------
Wallet Info:
-----------
{'avoid_reuse': False,
'balance': Decimal('0.07160443'),
'hdseedid': '6dko666b1cc0d69b7eb0539l89eba7b6390kdj02',
'immature_balance': Decimal('0E-8'),
'keypoololdest': 1542245729,
'keypoolsize': 999,
'keypoolsize_hd_internal': 1000,
'paytxfee': Decimal('0E-8'),
'private_keys_enabled': True,
'scanning': False,
'txcount': 9,
'unconfirmed_balance': Decimal('0E-8'),
'walletname': '',
'walletversion': 169900}
---------------------------------------------------------------
```
Outros comandos informativos como `getblockchaininfo`, `getnetworkinfo`, `getpeerinfo` e `getblockchaininfo` funcionarão de forma semelhante.
Outros comandos podem fornecer informações específicas sobre elementos selecionados na sua carteira.
### Recuperando um Array
O RPC `listtransactions` permite que observemos as 10 transações mais recentes do nosso sistema (ou algum conjunto arbitrário de transações usando os argumentos `count` e `skip`). Ele mostra como um comando RPC pode retornar uma matriz simples de ser manipulada:
```py
tx_list = rpc_client.listtransactions()
pprint(tx_list)
```
### Explorando um UTXO
Da mesma forma, podemos usar o `listunspent` para obter uma matriz de UTXOs:
```py
print("Exploring UTXOs")
## List UTXOs
utxos = rpc_client.listunspent()
print("Utxos: ")
print("-----")
pprint(utxos)
print("------------------------------------------\n")
```
Para manipular uma matriz como a retornada de `listtransactions` ou` listunpsent`, você apenas pega o item apropriado do elemento apropriado da matriz:
```
## Select a UTXO - first one selected here
utxo_txid = utxos[0]['txid']
```
Para o `listunspent`, obtemos um `txid`. Podemos recuperar as informações sobre ele com o comando `gettransaction` e, em seguida, decodificá-lo com um `decoderawtransaction`:
```
utxo_hex = rpc_client.gettransaction(utxo_txid)['hex']
utxo_tx_details = rpc_client.decoderawtransaction(utxo_hex)
print("Details of Utxo with txid:", utxo_txid)
print("---------------------------------------------------------------")
print("UTXO Details:")
print("------------")
pprint(utxo_tx_details)
print("---------------------------------------------------------------\n")
```
Este código está disponível no arquivo [walletinfo.py](../src/18_4_walletinfo.py).
```
$ python3 walletinfo.py
---------------------------------------------------------------
Wallet Info:
-----------
{'avoid_reuse': False,
'balance': Decimal('0.01031734'),
'hdseedid': 'da5a1b058deb9e51ecffef1b0ddc069a5dfb2c5f',
'immature_balance': Decimal('0E-8'),
'keypoololdest': 1596567843,
'keypoolsize': 1000,
'keypoolsize_hd_internal': 999,
'paytxfee': Decimal('0E-8'),
'private_keys_enabled': True,
'scanning': False,
'txcount': 6,
'unconfirmed_balance': Decimal('0E-8'),
'walletname': '',
'walletversion': 169900}
---------------------------------------------------------------
Utxos:
-----
[{'address': 'mv9cjEnS2o1EygBMdrz99LzhM8KeEMoXDg',
'amount': Decimal('0.00001000'),
'confirmations': 1180,
'desc': "pkh([ce0c7e14/0'/0'/25']02d0541b9211aecd25913f7fdecfc1b469215fa326d52067b1b3f7efbd12316472)#n06pq9q5",
'label': '-addresstype',
'safe': True,
'scriptPubKey': '76a914a080d1a10f5e7a02d0a291f118982ed19e8cfcd788ac',
'solvable': True,
'spendable': True,
'txid': '84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e',
'vout': 0},
{'address': 'tb1qrcf8c29966tvqxhwrtd2se3rj6jeqtll3r46a4',
'amount': Decimal('0.01029734'),
'confirmations': 1180,
'desc': "wpkh([ce0c7e14/0'/1'/26']02c581259ba7e6aef6d7ea23adb08f7c7f10c4c678f2e097a4074639e7685d4805)#j3pctfhf",
'safe': True,
'scriptPubKey': '00141e127c28a5d696c01aee1adaa8662396a5902fff',
'solvable': True,
'spendable': True,
'txid': '84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e',
'vout': 1},
{'address': 'mzDxbtYY3LBBBJ6HhaBAtnHv6c51BRBTLE',
'amount': Decimal('0.00001000'),
'confirmations': 1181,
'desc': "pkh([ce0c7e14/0'/0'/23']0377bdd176f985b4af2f6bdbb22c2925b6007b6c07ba171f75e65990c002615e98)#3y6ef6vu",
'label': '-addresstype',
'safe': True,
'scriptPubKey': '76a914cd339342b06042bb986a45e73d56db46acc1e01488ac',
'solvable': True,
'spendable': True,
'txid': '1679bee019c61608340b79810377be2798efd4d2ec3ace0f00a1967af70666b9',
'vout': 1}]
------------------------------------------
Details of Utxo with txid: 84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e
---------------------------------------------------------------
UTXO Details:
------------
{'hash': '0c6c27f58f122329bbc53a91f290b35ce23bd2708706b21a04cdc387dc8e2fd9',
'locktime': 1831103,
'size': 225,
'txid': '84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e',
'version': 2,
'vin': [{'scriptSig': {'asm': '', 'hex': ''},
'sequence': 4294967294,
'txid': '1679bee019c61608340b79810377be2798efd4d2ec3ace0f00a1967af70666b9',
'txinwitness': ['3044022014b3e2359fb46d8cbc4cd30fa991b455edfa4b419a4c64a53fcdfc79e3ca89db022010cefc3268bc252d55f1982c426328b709b47d02332def9e2efb3b12de2cf0d301',
'0351b470e87b44e8e9607acf09b8d4543c51c93c17dc741176319e60202091f2be'],
'vout': 0}],
'vout': [{'n': 0,
'scriptPubKey': {'addresses': ['mv9cjEnS2o1EygBMdrz99LzhM8KeEMoXDg'],
'asm': 'OP_DUP OP_HASH160 '
'a080d1a10f5e7a02d0a291f118982ed19e8cfcd7 '
'OP_EQUALVERIFY OP_CHECKSIG',
'hex': '76a914a080d1a10f5e7a02d0a291f118982ed19e8cfcd788ac',
'reqSigs': 1,
'type': 'pubkeyhash'},
'value': Decimal('0.00001000')},
{'n': 1,
'scriptPubKey': {'addresses': ['tb1qrcf8c29966tvqxhwrtd2se3rj6jeqtll3r46a4'],
'asm': '0 1e127c28a5d696c01aee1adaa8662396a5902fff',
'hex': '00141e127c28a5d696c01aee1adaa8662396a5902fff',
'reqSigs': 1,
'type': 'witness_v0_keyhash'},
'value': Decimal('0.01029734')}],
'vsize': 144,
'weight': 573}
---------------------------------------------------------------
```
## Crindo um Endereço
Criar um novo endereço com Python 3 requer apenas o uso de um RPC como `getnewaddress` ou `getrawchangeaddress`.
```
new_address = rpc_client.getnewaddress("Learning-Bitcoin-from-the-Command-Line")
new_change_address = rpc_client.getrawchangeaddress()
```
Neste exemplo, usamos o comando `getnewaddress` junto com um argumento: o rótulo `Learning-Bitcoin-from-the-Command-Line`.
## Enviando uma Transação
A criação de uma transação no Python 3 requer a combinação de alguns dos exemplos anteriores, de criação de endereços e de recuperação de UTXOs, com alguns comandos novos do RPC para criar, assinar e enviar uma transação, da mesma forma que fizemos anteriormente na linha de comando.
Existem cinco etapas:
0. Criar dois endereços, um que funcionará como destinatário e outro para o troco;
1. Selecionar um UTXO e definir os detalhes da transação;
2. Criar uma transação bruta;
3. Assinar a transação bruta com a chave privada do UTXO;
4. Transmitir a transação na Testnet do bitcoin.
### 1. Selecionando o UTXO e Definindo os Detalhes da Transação
No trecho de código a seguir, primeiro selecionaremos o UTXO que gostaríamos de gastar. Em seguida, iremos obter o endereço, id da transação e o índice vetorial da saída.
```py
utxos = rpc_client.listunspent()
selected_utxo = utxos[0] # novamente, selecionando o primeiro utxo aqui
utxo_address = selected_utxo['address']
utxo_txid = selected_utxo['txid']
utxo_vout = selected_utxo['vout']
utxo_amt = float(selected_utxo['amount'])
```
Em seguida, também recuperamos o endereço do destinatário para o qual desejamos enviar os bitcoins, calculamos a quantidade de bitcoins que desejamos enviar e calculamos a taxa de minerador e o valor do troco. Aqui, o valor é dividido arbitrariamente em dois e uma taxa de minerador é definida arbitrariamente.
```py
recipient_address = new_address
recipient_amt = utxo_amt / 2 # enviando metade das moedas para o recebedor
miner_fee = 0.00000300 # escolha uma taxa apropriada baseada no tamanho da sua transação
change_address = new_change_address
change_amt = float('%.8f'%((utxo_amt - recipient_amt) - miner_fee))
```
> :warning: **AVISO:** Obviamente, um programa real faria escolhas mais sofisticadas sobre qual UTXO usar, o que fazer com os fundos e qual taxa de mineração pagar.
### 2. Criando uma Transação Bruta
Agora temos todas as informações para enviar uma transação, mas antes de enviá-la, devemos criá-la.
```py
txids_vouts = [{"txid": utxo_txid, "vout": utxo_vout}]
addresses_amts = {f"{recipient_address}": recipient_amt, f"{change_address}": change_amt}
unsigned_tx_hex = rpc_client.createrawtransaction(txids_vouts, addresses_amts)
```
Lembre-se de que o formato do comando `createrawtransaction` é:
```$ bitcoin-cli createrawtransaction '[{"txid": <utxo_txid>, "vout": <vector_id>}]' '{"<address>": <amount>}'```
O `txids_vouts` é, portanto, uma lista, e o `address_amts` é um dicionário python, para combinar com o formato de `createrawtransaction`.
Se quisermos ver mais sobre os detalhes da transação que criamos, podemos usar `decoderawtransaction`, tanto no Python 3 quanto com `bitcoin-cli`.
### 3. Assinar Transação Bruta
Assinar uma transação geralmente é a parte mais complicada do envio de uma transação, quando olhamos a parte de programação. Aqui recuperamos uma chave privada de um endereço com `dumpprivkey` e a colocamos em uma matriz:
```py
address_priv_key = [] # list of priv keys of each utxo
address_priv_key.append(rpc_client.dumpprivkey(utxo_address))
```
Depois, usamos esse array, que deve conter as chaves privadas de cada UTXO que está sendo gasto, para assinar nosso `unsigned_tx_hex`:
```py
signed_tx = rpc_client.signrawtransactionwithkey(unsigned_tx_hex, address_priv_key)
```
Isso retornará um objeto JSON com o hex da transação assinada e se foi assinado completamente ou não:
### 4. Transmitindo a Transação
Finalmente, estamos prontos para transmitir a transação assinada na rede Bitcoin:
```py
send_tx = rpc_client.sendrawtransaction(signed_tx['hex'])
```
### Executando Nosso Código
[Este código](../src/18_4_sendtx.py) está cheio de instruções com `print` para demonstrar todos os dados disponíveis a cada momento:
```
$ python3 sendtx.py
Creating a Transaction
---------------------------------------------------------------
Transaction Details:
-------------------
UTXO Address.......: mv9cjEnS2o1EygBMdrz99LzhM8KeEMoXDg
UTXO Txid..........: 84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e
Vector ID of Output: 0
UTXO Amount........: 1e-05
Tx Amount..........: 5e-06
Recipient Address..: tb1qca0elxxqzw5xc0s3yq5qhapzzj90ka0zartu6y
Change Address.....: tb1qrveukqrvqm9h6fua99xvcxgnvdx507dg8e8hrt
Miner Fee..........: 3e-06
Change Amount......: 2e-06
---------------------------------------------------------------
---------------------------------------------------------------
Unsigned Transaction Hex: 02000000015e53fb6f63b7defa28e61c28cfc3033361138a0d33dd1fad29ae58c6fe7f20840000000000ffffffff02f401000000000000160014c75f9f98c013a86c3e1120280bf422148afb75e2c8000000000000001600141b33cb006c06cb7d279d294ccc1913634d47f9a800000000
---------------------------------------------------------------
---------------------------------------------------------------
Signed Transaction:
----------------------
{'complete': True,
'hex': '02000000015e53fb6f63b7defa28e61c28cfc3033361138a0d33dd1fad29ae58c6fe7f2084000000006a47304402205da9b2234ea057c9ef3b7794958db6c650c72dedff1a90d2915147a5f6413f2802203756552aba0dd8ebd71b0f28341becc01b28d8b28af063d7c8ce89f9c69167f8012102d0541b9211aecd25913f7fdecfc1b469215fa326d52067b1b3f7efbd12316472ffffffff02f401000000000000160014c75f9f98c013a86c3e1120280bf422148afb75e2c8000000000000001600141b33cb006c06cb7d279d294ccc1913634d47f9a800000000'}
---------------------------------------------------------------
---------------------------------------------------------------
TXID of sent transaction: 187f8baa222f9f37841d966b6bad59b8131cfacca861cbe9bfc8656bd16a44cc
```
## Resumo: Acessando o Bitcoind com Python
Acessar Bitcoind com Python é muito fácil usando a biblioteca `python-bitcoinrpc`. A primeira coisa a se fazer é estabelecer uma conexão com nossa instância `bitcoind`, então podemos fazer todas as chamadas da API do Bitcoin conforme descrito nos documentos do Bitcoin Core. Isso torna mais fácil criar programas pequenos ou grandes para gerenciar nosso próprio node, verificando saldos ou criando aplicações interessantes, conforme acessamos todo o poder do `bitcoin-cli`.
## O Que Vem Depois?
Vamos aprender mais sobre "Conversando com o Bitcoind com Outras Linguagens" na seção [§18.5: Acessando o Bitcoind com Rust](18_5_Accessing_Bitcoind_with_Rust.md).
## Variante: Construindo Python da Fonte
Se precisarmos instalar o Python 3 a partir do código-fonte, precisaremos seguir estas instruções, e então continuar com ["Criando um projeto BitcoinRPC"](18_4_Accessing_Bitcoind_with_Python.md#creating-a-bitcoinrpc-project).
### 1. Instalando as Dependências
```sh
$ sudo apt-get install build-essential checkinstall
$ sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev
```
### 2. Baixando e Extraindo o Python
```sh
$ wget https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz
$ tar -xzf Python-3.8.3.tgz
```
### 3. Compilando o Código-Fonte Python e Verificando a Instalação:
```sh
$ cd Python-3.8.3
$ sudo ./configure --enable-optimizations
$ sudo make -j 8 # coloque o número de núcleos que você quer usar do seu sistema para acelerar o processo
$ sudo make altinstall
$ python3.8 --version
```
Depois de obter o retorno da versão, podemos remover o arquivo de instalação:
```sh
$ rm Python-3.8.3.tgz
```

View File

@ -0,0 +1,362 @@
# 18.5: Acessando o Bitcoind com Rust
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Esta seção explica como interagir com o `bitcoind` usando a linguagem de programação Rust e o [`bitcoincore-rpc` crate](https://github.com/rust-bitcoin/rust-bitcoincore-rpc).
## Configurando o Rust
Precisaremos instalar o Rust e o Cargo.
Eles podem ser instalados via `curl`. Basta usar a instalação "padrão":
```vim
$ curl https://sh.rustup.rs -sSf | sh
```
Se tudo correr bem, veremos:
```vim
Rust is installed now. Great!
```
Em seguida, precisaremos fazer o logout e o login novamente ou então adicionar o diretório binário do Cargo ao nosso caminho manualmente:
```
$ source $HOME/.cargo/env
```
### Configurando o `bitcoincore-rpc`
Para a maioria das linguagens de programação, precisamos instalar uma biblioteca Bitcoin RPC antes de criar nosso primeiro projeto, mas aqui iremos fazê-lo como parte da criação do nosso projeto.
### Criando um Projeto `bitcoincore-rpc`
Podemos criar um novo projeto usando `cargo new btc_test`:
```
$ cargo new btc_test
Created binary (application) `btc_test` package
```
Isso criará um diretório `btc_test` que contém um exemplo de código-fonte "hello world" que está no `src/main.rs` e um arquivo `Cargo.toml`.
Vamos compilar e executar nosso código com `cargo run`:
```
$ cd btc_test
$ cargo run
Compiling btc_test v0.1.0 (/home/standup/btc_test)
Finished dev [unoptimized + debuginfo] target(s) in 0.14s
Running `target/debug/btc_test`
Hello, world!
```
> :information_source: **NOTA:** se encontrarmos o erro `linker cc not found`, teremos que instalar um
Compilador C. Se estivermos no Linux, podemos instalar com as [ferramentas de desenvolvimento](https://www.ostechnix.com/install-development-tools-linux/).
Para acessar o crate (biblioteca) `bitcoincore-rpc`, devemos adicioná-lo ao nosso arquivo `Cargo.toml` na seção `dependencies`:
```rust
[dependencies]
bitcoincore-rpc = "0.11.0"
```
Quando usarmos o comando `cargo run` novamente, ele irá instalar os crates e suas (numerosas) dependências.
```
$ cargo run
Updating crates.io index
...
Compiling bitcoin v0.23.0
Compiling bitcoincore-rpc-json v0.11.0
Compiling bitcoincore-rpc v0.11.0
Compiling btc_test v0.1.0 (/home/standup/btc_test)
Finished dev [unoptimized + debuginfo] target(s) in 23.56s
Running `target/debug/btc_test`
Hello, world!
```
Quando estivermos usando o `bitcoin-rpc`, normalmente precisaremos incluir o seguinte:
```
use bitcoincore_rpc::{Auth, Client, RpcApi};
```
## Construindo Nossa Conexão
Para criarmos um `RPC client` do Bitcoin, vamos modificar o `src/main.rs`:
```rust
use bitcoincore_rpc::{Auth, Client, RpcApi};
fn main() {
let rpc = Client::new(
"http://localhost:18332".to_string(),
Auth::UserPass("StandUp".to_string(), "password".to_string()),
)
.unwrap();
}
```
Como de costume, vamos nos certificar de inserir nosso nome de usuário e senha corretos no `~/.bitcoin/bitcoin.conf`. Aqui, eles serão usados como argumentos para `Auth :: UserPass`.
> :link: **TESTNET vs MAINNET:** E, como de costume, use a porta 8332 para a Mainnet.
Quando terminarmos, também devemos fechar nossa conexão:
```rust
let _ = rpc.stop().unwrap();
```
O `cargo run` deve compilar e executar o exemplo com sucesso com um aviso `warning: unused variable: rpc`
### Fazendo uma Chamada RPC
As chamadas RPC são feitas usando o `rpc Client` que criamos:
```rust
let mining_info = rpc.get_mining_info().unwrap();
println!("{:#?}", mining_info);
```
Geralmente, as palavras na chamada RPC são separadas por `_`s. Uma lista completa está disponível na [documentação do crate](https://crates.io/crates/bitcoincore-rpc).
### Fazendo uma Chamada RPC com Argumentos
O envio de uma chamada RPC com argumentos usando Rust requer apenas o conhecimento de como a função é apresentada. Por exemplo, a função `get_block` é definida da seguinte forma na [documentação](https://docs.rs/bitcoincore-rpc/0.11.0/bitcoincore_rpc/trait.RpcApi.html#method.get_block):
```rust
fn get_block(&self, hash: &BlockHash) -> Result<Block>
```
Só precisamos permitir que ele pegue emprestado um blockhash, que pode ser recuperado (por exemplo) usando o comando `get_best_block_hash`.
Aqui está o código completo para recuperar um hash de bloco, transformando-o em um bloco e imprimi-lo.
```
let hash = rpc.get_best_block_hash().unwrap();
let block = rpc.get_block(&hash).unwrap();
println!("{:?}", block);
```
> **NOTA:** Outra chamada possível que consideramos para esta seção é a `get_address_info`, mas, infelizmente, no momento de escrita, a função `bitcoincore-rpc` não funciona com versões recentes do Bitcoin Core devido ao crate não abordar as mais recentes mudanças de API no Bitcoin Core. Esperamos que isso seja resolvido no próximo lançamento do crate, mas, enquanto isso programador, _cuidado_.
### Executando Nosso Código
Podemos acessar o [código src](../src/18_5_main-getinfo.rs) e executá-lo. Infelizmente, a informação do "Block" sairá um pouco feia porque este exemplo não inclui uma biblioteca para embelezá-la.
```
$ cargo run
Compiling btc_test v0.1.0 (/home/standup/btc_test)
Finished dev [unoptimized + debuginfo] target(s) in 1.61s
Running `target/debug/btc_test`
GetMiningInfoResult {
blocks: 1832335,
current_block_weight: None,
current_block_tx: None,
difficulty: 4194304.0,
network_hash_ps: 77436285865245.1,
pooled_tx: 4,
chain: "test",
warnings: "Warning: unknown new rules activated (versionbit 28)",
}
Block { header: BlockHeader { version: 541065216, prev_blockhash: 000000000000027715981d5a3047daf6819ea3b8390b73832587594a2074cbf5, merkle_root: 4b2e2c2754b6ed9cf5c857a66ed4c8642b6f6b33b42a4859423e4c3dca462d0c, time: 1599602277, bits: 436469756, nonce: 218614401 }, txdata: [Transaction { version: 1, lock_time: 0, input: [TxIn { previous_output: OutPoint { txid: 0000000000000000000000000000000000000000000000000000000000000000, vout: 4294967295 }, script_sig: Script(OP_PUSHBYTES_3 8ff51b OP_PUSHBYTES_22 315448617368263538434f494e1d00010320a48db852 OP_PUSHBYTES_32 <push past end>), sequence: 4294967295, witness: [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] }], output: [TxOut { value: 19721777, script_pubkey: Script(OP_HASH160 OP_PUSHBYTES_20 011beb6fb8499e075a57027fb0a58384f2d3f784 OP_EQUAL) }, TxOut { value: 0, script_pubkey: Script(OP_RETURN OP_PUSHBYTES_36 aa21a9ed63363f3620ab5e38b8860a50c84050e5ec31af3636bbd73f01ba9f14103100ee) }] }, Transaction { version: 2, lock_time: 1832282, input: [TxIn { previous_output: OutPoint { txid: cbf880f73d421baf0aa4f0d28e63ba00e5bc6bd934b91eb0641354ce5ca42f7e, vout: 0 }, script_sig: Script(OP_PUSHBYTES_22 00146b8dbd32e5deb90d22934e1513bae6e70156cd50), sequence: 4294967294, witness: [[48, 68, 2, 32, 13, 89, 205, 30, 67, 24, 196, 83, 65, 224, 44, 138, 98, 58, 81, 135, 132, 209, 23, 166, 23, 44, 3, 228, 95, 102, 166, 214, 62, 38, 155, 147, 2, 32, 119, 2, 34, 246, 148, 255, 166, 10, 90, 52, 242, 32, 74, 241, 123, 148, 89, 199, 197, 3, 152, 134, 242, 215, 109, 61, 241, 241, 13, 70, 86, 207, 1], [2, 192, 145, 170, 206, 55, 4, 36, 138, 145, 217, 50, 19, 73, 130, 136, 245, 131, 184, 142, 239, 75, 13, 67, 17, 177, 57, 86, 151, 139, 89, 35, 109]] }], output: [TxOut { value: 1667908, script_pubkey: Script(OP_HASH160 OP_PUSHBYTES_20 908ca2b8b49ccf53efa2226afa85f6cc58dfd7e7 OP_EQUAL) }, TxOut { value: 9093, script_pubkey: Script(OP_DUP OP_HASH160 OP_PUSHBYTES_20 42ee67664ce16edefc68ad0e4c5b7ce2fc2ccc18 OP_EQUALVERIFY OP_CHECKSIG) }] }, ...] }
```
## Procurando por Fundos
Podemos procurar fundos sem argumentos opcionais usando a função `get_balance`:
```rust
let balance = rpc.get_balance(None, None).unwrap();
println!("Balance: {:?} BTC", balance.as_btc());
```
Conforme mostrado, a função `as_btc()` ajuda a gerar o saldo em um formato legível:
```
Balance: 3433.71692741 BTC
```
## Criando um Endereço
A criação de um endereço demonstra como fazer uma chamada RPC com vários argumentos opcionais especificados (por exemplo, um rótulo e um tipo de endereço).
```rust
// Gerar um novo endereço
let myaddress = rpc
.get_new_address(Option::Some("BlockchainCommons"), Option::Some(json::AddressType::Bech32))
.unwrap();
println!("address: {:?}", myaddress);
```
Isso também exigirá que tragamos a definição `json` para o escopo:
```rust
use bitcoincore_rpc::{json, Auth, Client, RpcApi};
```
## Enviando uma Transação
Agora temos tudo de que precisamos para criar uma transação, o que será feito em cinco partes:
1. Listar UTXOs;
2. Preencher variáveis;
3. Criar transação bruta;
4. Assinar transação;
5. Enviar transação.
### 1. Listando os UTXOs
Para iniciar a criação de uma transação, primeiro encontramos um UTXO para usar. O seguinte pega o primeiro UTXO com pelo menos 0,01 BTC:
```rust
let unspent = rpc
.list_unspent(
None,
None,
None,
None,
Option::Some(json::ListUnspentQueryOptions {
minimum_amount: Option::Some(Amount::from_btc(0.01).unwrap()),
maximum_amount: None,
maximum_count: None,
minimum_sum_amount: None,
}),
)
.unwrap();
let selected_tx = &unspent[0];
println!("selected unspent transaction: {:#?}", selected_tx);
```
Isso nos exigirá trazer mais estruturas para o escopo:
```rust
use bitcoincore_rpc::bitcoin::{Address, Amount};
```
Podemos observar que estamos passando cinco variáveis ao comando `list_unspent`. Os primeiros quatro (`minconf`,` maxconf`, `address` e `include_unsafe`) não são usados aqui. O quinto é o `query_options`, que não usamos antes, mas temos algumas opções de filtragem poderosas, incluindo a capacidade de olhar apenas para os UTXOs com um certo valor, mínimo ou máximo.
### 2. Preenchendo as Variáveis
Para começar a preencher as variáveis que precisaremos para criar uma nova transação, criamos a entrada do `txid` e do `vout` ao UTXO que selecionamos:
```rust
let selected_utxos = json::CreateRawTransactionInput {
txid: selected_tx.txid,
vout: selected_tx.vout,
sequence: None,
};
```
Em seguida, podemos calcular a quantia que vamos gastar subtraindo uma taxa de mineração dos fundos no UTXO:
```rust
// enviar todo o bitcoin no UTXO exceto um valor pequeno que será pago aos mineradores
let unspent_amount = selected_tx.amount;
let amount = unspent_amount - Amount::from_btc(0.00001).unwrap();
```
Por fim, podemos criar um mapa do hash do endereço e da quantidade para formar a saída:
```rust
let mut output = HashMap::new();
output.insert(
myaddress.to_string(),
amount,
);
```
Outra característica é necessária para a variável de saída: o `HashMap`. Ele nos permite armazenar
valores por chave, que iremos precisar para representar a informação `{address: amount}`.
```rust
use std::collections::HashMap;
```
### 3. Criando a Transação Bruta
Agora estamos prontos para criar uma transação bruta:
```rust
let unsigned_tx = rpc
.create_raw_transaction(&[selected_utxos], &output, None, None)
.unwrap();
```
### 4. Assinando a Transação
A assinatura da transação pode ser feita com um simples uso do `sign_raw_transaction_with_wallet`:
```rust
let signed_tx = rpc
.sign_raw_transaction_with_wallet(&unsigned_tx, None, None)
.unwrap();
println!("signed tx {:?}", signed_tx.transaction().unwrap());
```
### 5. Enviando a Transação
Finalmente, podemos transmitir a transação:
```rust
let txid_sent = rpc
.send_raw_transaction(&signed_tx.transaction().unwrap())
.unwrap();
println!("{:?}", txid_sent);
```
### Executando Nosso Código
Agora podemos executar o código completo do [src](../src/18_5_main-sendtx.rs).
```
$ cargo run
Compiling btc_test v0.1.0 (/home/standup/btc_test)
warning: unused variable: `unspent_amount`
--> src/main.rs:86:9
|
86 | let unspent_amount = selected_tx.amount;
| ^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unspent_amount`
|
= note: `#[warn(unused_variables)]` on by default
warning: 1 warning emitted
Finished dev [unoptimized + debuginfo] target(s) in 2.11s
Running `target/debug/btc_test`
Balance: 0.01031434 BTC
address: tb1qx5jz36xgt9q2rkh4daee8ewfj0g5z05v8qsua2
selected unspent transaction: ListUnspentResultEntry {
txid: 84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e,
vout: 1,
address: Some(
tb1qrcf8c29966tvqxhwrtd2se3rj6jeqtll3r46a4,
),
label: None,
redeem_script: None,
witness_script: None,
script_pub_key: Script(OP_0 OP_PUSHBYTES_20 1e127c28a5d696c01aee1adaa8662396a5902fff),
amount: Amount(1029734 satoshi),
confirmations: 1246,
spendable: true,
solvable: true,
descriptor: Some(
"wpkh([ce0c7e14/0\'/1\'/26\']02c581259ba7e6aef6d7ea23adb08f7c7f10c4c678f2e097a4074639e7685d4805)#j3pctfhf",
),
safe: true,
}
unsigned tx Transaction {
version: 2,
lock_time: 0,
input: [
TxIn {
previous_output: OutPoint {
txid: 84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e,
vout: 1,
},
script_sig: Script(),
sequence: 4294967295,
witness: [],
},
],
output: [
TxOut {
value: 1028734,
script_pubkey: Script(OP_0 OP_PUSHBYTES_20 352428e8c85940a1daf56f7393e5c993d1413e8c),
},
],
}
signed tx Transaction { version: 2, lock_time: 0, input: [TxIn { previous_output: OutPoint { txid: 84207ffec658ae29ad1fdd330d8a13613303c3cf281ce628fadeb7636ffb535e, vout: 1 }, script_sig: Script(), sequence: 4294967295, witness: [[48, 68, 2, 32, 98, 230, 199, 113, 156, 242, 158, 42, 148, 229, 239, 44, 9, 226, 127, 219, 72, 51, 26, 135, 44, 212, 179, 200, 213, 63, 56, 167, 0, 55, 236, 235, 2, 32, 41, 43, 30, 109, 60, 162, 124, 67, 20, 126, 4, 107, 124, 95, 9, 200, 132, 246, 147, 235, 176, 55, 59, 45, 190, 18, 211, 201, 143, 62, 163, 36, 1], [2, 197, 129, 37, 155, 167, 230, 174, 246, 215, 234, 35, 173, 176, 143, 124, 127, 16, 196, 198, 120, 242, 224, 151, 164, 7, 70, 57, 231, 104, 93, 72, 5]] }], output: [TxOut { value: 1028734, script_pubkey: Script(OP_0 OP_PUSHBYTES_20 352428e8c85940a1daf56f7393e5c993d1413e8c) }] }
b0eda3517e6fac69e58ae315d7fe7a1981e3a858996cc1e3135618cac9b79d1a
```
## Resumo: Acessando o Bitcoind com Rust
O `bitcoincore-rpc` é um crate simples e robusto que nos permitirá interagir com o Bitcoin RPC usando Rust. No entanto, no momento em que este livro foi escrito, ele ficou para trás no Bitcoin Core, o que pode causar alguns problemas de uso.
## O Que Vem Depois?
Vamos aprender mais sobre "Conversando com o Bitcoind com Outras Linguagens" na seção [§18.6: Acessando o Bitcoind com Swift](18_6_Accessing_Bitcoind_with_Swift.md).

View File

@ -0,0 +1,463 @@
# 18.6: Acessando o Bitcoind com Swift
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Esta seção explica como interagir com o `bitcoind` usando a linguagem de programação Swift e seu próprio cliente RPC.
## Configurando o Swift no Mac
Até o momento, construímos todos os nossos ambientes de desenvolvimento de linguagem de programação alternativa em nosso node virtual no Debian. No entanto, essa não é a melhor plataforma para o Swift. Embora haja uma versão do Swift disponível para plataformas Ubuntu, ela não possui todos os recursos e funciona de maneira um pouco diferente do Swift nativo do Mac. Uma "variante" no final desta seção explica como configurá-lo, mas esteja avisado de que estaremos em um território desconhecido.
Ao invés disso, sugerimos a criação de um ambiente Swift ideal em um Mac. Existem quatro etapas principais para fazer isso.
### 1. Instalando o Xcode
Vamos precisar do `Xcode`, o ambiente de desenvolvimento integrado para o Swift e para o Objective-C. Isso pode ser facilmente instalado acessando a Mac App Store e baixando o Xcode.
#### Alternativa: Instalando Manualmente
Algumas pessoas desaconselham a instalação da App Store porque é tudo ou nada. Também não funcionará se estivermos usando o Mojave, pois desejaremos evitar as incompatibilidades do Catalina. Nesse caso, podemos fazer o download diretamente da [Área do desenvolvedor](https://developer.apple.com/download/more/) na Apple.
Se estivermos usando o Mojave, precisaremos do arquivo `xip` para o Xcode 10.3.1. Caso contrário, podemos utilizar o mais recente.
Depois de baixado, podemos clicar no `xip` para extraí-lo e mover o aplicativo Xcode para a pasta de Aplicativos.
De qualquer forma, devemos ter o Xcode instalado na pasta de Aplicativos no final desta etapa.
### 2. Instalando o Servidor Gordian
Também vamos precisar de um node Bitcoin em nosso Mac, para que possamos nos comunicar com ele. Tecnicamente, poderíamos usar um node remoto e acessá-lo com o login e senha RPC pela rede. No entanto, sugerimos a instalação do full node diretamente no Mac, porque essa é a configuração mais segura e limpa, garantindo que nenhuma das comunicações saia de nossa máquina.
Para instalar facilmente um full node em nosso Mac, podemos usar o [GordianServer for MacOS](https://github.com/BlockchainCommons/GordianServer-macOS) da Blockchain Commons. Podemos seguir as [instruções de instalação](https://github.com/BlockchainCommons/GordianServer-macOS#installation-instructions) no README, mas geralmente tudo que precisamos fazer é baixar o arquivo `dmg` atual, abri-lo e instalar a aplicação em nosso diretório de aplicações.
Depois, vamos executar o aplicativo GordianServer e dizer a ele para `Start` na Testnet.
> :link: **TESTNET vs. MAINNET:** Ou `Start` na Mainnet.
#### 3. Tornando Nosso bitcoin-cli Gordian Acessível
Quando desejarmos acessar o `bitcoin-cli` criado pelo GordianServer em nosso Mac local, podemos encontrá-lo em `~/.standup/BitcoinCore/bitcoin-0.20.1/bin/bitcoin-cli`.
Podemos criar um alias para isso:
```
alias bitcoin-cli="~/.standup/BitcoinCore/bitcoin-0.20.1/bin/bitcoin-cli -testnet"
```
> :link: **TESTNET vs. MAINNET:** Obviamente, o parâmetro `-testnet` só é necessário se estivermos rodando na testnet.
### 4. Encontrando Nossas Informações do GordianServer
Finalmente, precisaremos de nossas informações de `rpcuser` e `rpcpassword`. Essas informações estarão em `~/Library/Application Support/Bitcoin/bitcoin.conf` por padrão no Gordian.
```
$ grep rpc ~/Library/Application\ Support/Bitcoin/bitcoin.conf
rpcuser=oIjA53JC2u
rpcpassword=ebVCeSyyM0LurvgQyi0exWTqm4oU0rZU
...
```
## Construindo Nossa Conexão Manualmente
No momento em que este artigo foi escrito, não havia uma biblioteca Bitcoin RPC atualizada e simples de ser usada, que fosse específica para Swift, algo que pudéssemos baixar e começar a usar imediatamente. Portanto, faremos algo que nunca fizemos antes: construir uma conexão RPC manualmente.
### Grave o Transmissor RPC
Isso requer apenas a escrita de uma função que passe os comandos RPC para o `bitcoind` no formato correto:
```
func makeCommand(method: String, param: Any, completionHandler: @escaping (Any?) -> Void) -> Void {
```
As conexões RPC para o `bitcoind` usam o protocolo HTML, o que significa que precisamos fazer três coisas: Criar uma URL, fazer um URLRequest e iniciar uma URLSession.
#### 1. Criando uma URL
Dentro da função, precisamos criar uma URL a partir do nosso IP, porta, `rpcuser`, `rpcpassword` e wallet:
```
let testnetRpcPort = "18332"
let nodeIp = "127.0.0.1:\(testnetRpcPort)"
let rpcusername = "oIjA53JC2u"
let rpcpassword = "ebVCeSyyM0LurvgQyi0exWTqm4oU0rZU"
let walletName = ""
```
A conexão RPC real com o Bitcoin Core é construída usando uma URL no formato "http://rpcusername:rpcpassword@nodeIp/walletName":
```
let walletUrl = "http://\(rpcusername):\(rpcpassword)@\(nodeIp)/\(walletName)"
let url = URL(string: walletUrl)
```
Isso significa que nossas variáveis de amostra resultam na seguinte URL:
```
http://oIjA53JC2u:ebVCeSyyM0LurvgQyi0exWTqm4oU0rZU@127.0.0.1:18332/
```
Que deve se parecer muito com a URL usada em algumas das seções anteriores para conexões RPC.
#### 2. Criando uma URLRequest
Com essa URL em mãos, agora podemos criar um URLRequest, com o método `POST` e o tipo de conteúdo `text/plain`. O corpo HTTP será então o objeto JSON familiar que enviamos sempre que nos conectamos diretamente às portas RPC do Bitcoin Core, conforme demonstrado pela primeira vez ao usar o Curl na seção [§4.4](04_4__Interlude_Using_Curl.md).
```
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue("text/plain", forHTTPHeaderField: "Content-Type")
request.httpBody = "{\"jsonrpc\":\"1.0\",\"id\":\"curltest\",\"method\":\"\(method)\",\"params\":[\(param)]}".data(using: .utf8)
```
#### 3. Criando uma URLSession
Finalmente, estamos prontos para construir uma URLSession em torno da nossa URLRequest.
```
let session = URLSession(configuration: .default)
let task = session.dataTask(with: request as URLRequest) { data, response, error in
```
O manipulador de conclusão para `dataTask` precisa verificar se há erros:
```
do {
if error != nil {
//Handle the error
} else {
```
E então analisar os dados que estamos recebendo. Aqui, estamos pegando os resultados JSON e colocando-os em um `NSDictionary`:
```
if let urlContent = data {
do {
let json = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableLeaves) as! NSDictionary
```
Depois disso, há mais manipulação de erros e então podemos eventualmente retornar o `result` do dicionário usando o `CompletHandler` que definimos para a nova função `makeCommand`:
```
if let errorCheck = json["error"] as? NSDictionary {
if let errorMessage = errorCheck["message"] as? String {
print("FAILED")
print(errorMessage)
}
} else {
let result = json["result"]
completionHandler(result)
}
} catch {
//Handle error here
}
```
Claro que eventualmente teremos que dizer à `task` para que ela seja iniciada:
```
task.resume()
```
E isso é "tudo" o que precisamos fazer nessa interação RPC manual, usando uma linguagem de programação como o Swift.
> :pray: **AGRADECIMENTO:** Obrigado @Fonta1n3, que forneceu o [código principal](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/issues/137) para nosso Transmissor RPC.
### Fazendo uma Chamada RPC
Tendo escrito a função RPC `makeCommand`, podemos enviar uma chamada RPC executando-a. Aqui está `getblockchaininfo`:
```
let method = "getblockchaininfo"
let param = ""
makeCommand(method: method,param: param) { result in
print(result!)
}
```
### Fazendo uma Chamada RPC com Argumentos
Poderíamos da mesma forma obter a contagem de bloco atual a partir dessa informação e usá-la de modo redundante para obter o hash do bloco atual, usando o parâmetro `param`:
```
let method = "getblockchaininfo"
let param = ""
makeCommand(method: method,param: param) { result in
let blockinfo = result as! NSDictionary
let block = blockinfo["blocks"] as! NSNumber
let method = "getblockhash"
makeCommand(method: method,param: block) { result in
print("Blockhash for \(block) is \(result!)")
}
}
```
### Executando Nosso Código
O código completo está disponível no [diretório src/](../src/18_6_getinfo.playground). Carregue-o no playground Xcode e, em seguida, "Editor -> Executar Playground" e devemos obter resultados como:
```
{
bestblockhash = 00000000000000069725608ebc5b59e520572a8088cbc57ffa5ba87b7f300ac7;
blocks = 1836745;
chain = test;
chainwork = 0000000000000000000000000000000000000000000001cc3e9f8e0bc6b71196;
difficulty = "16508683.81195478";
headers = 1836745;
initialblockdownload = 0;
mediantime = 1601416765;
pruned = 0;
"size_on_disk" = 28205538354;
softforks = {
bip34 = {
active = 1;
height = 21111;
type = buried;
};
bip65 = {
active = 1;
height = 581885;
type = buried;
};
bip66 = {
active = 1;
height = 330776;
type = buried;
};
csv = {
active = 1;
height = 770112;
type = buried;
};
segwit = {
active = 1;
height = 834624;
type = buried;
};
};
verificationprogress = "0.999999907191804";
warnings = "Warning: unknown new rules activated (versionbit 28)";
}
Blockhash for 1836745 is 00000000000000069725608ebc5b59e520572a8088cbc57ffa5ba87b7f300ac7
```
## Procurando por Fundos
Com nosso novo `makeCommand` para funções RPC, podemos executar um comando como `getwalletinfo` ou `getbalance`:
```
var method = "getwalletinfo"
var param = ""
makeCommand(method: method,param: param) { result in
print(result!)
}
method = "getbalance"
makeCommand(method: method,param: param) { result in
let balance = result as! NSNumber
print("Balance is \(balance)")
}
```
Que irá retornar:
```
Balance is 0.01
{
"avoid_reuse" = 0;
balance = "0.01";
hdseedid = bf493318f548df8e25c390d6a7f70758fd6b3668;
"immature_balance" = 0;
keypoololdest = 1599723938;
keypoolsize = 999;
"keypoolsize_hd_internal" = 1000;
paytxfee = 0;
"private_keys_enabled" = 1;
scanning = 0;
txcount = 1;
"unconfirmed_balance" = 0;
walletname = "";
walletversion = 169900;
}
```
## Criando um Endereço
Criar um endereço é bastante simples, mas que tal criar um endereço legado com um rótulo específico? Isso requer dois parâmetros na nossa chamada RPC.
Uma vez que a simples função `makeCommand` desta seção apenas passa nossos `param`s como as entranhas de um objeto JSON, tudo o que precisamos fazer é formatar corretamente essas entranhas. Aqui está uma maneira para fazermos isso:
```
method = "getnewaddress"
param = "\"learning-bitcoin\", \"legacy\""
makeCommand(method: method,param: param) { result in
let address = result as! NSString
print(address)
}
```
Executá-lo no playground do Xcode produz o seguinte resultado:
```
mt3ZRsmXHVMMqYQPJ8M74QjF78bmqrdHZF
```
Esse resultado é obviamente um endereço legado; seu rótulo pode então ser verificado na linha de comando:
```
$ bitcoin-cli getaddressesbylabel "learning-bitcoin"
{
"mt3ZRsmXHVMMqYQPJ8M74QjF78bmqrdHZF": {
"purpose": "receive"
}
}
```
Sucesso!
> :information_source: **NOTA:** Como costumamos dizer nesses exemplos de programação, um programa do mundo real seria muito mais sofisticado. Em particular, gostaríamos de poder enviar um objeto JSON real como um parâmetro e, em seguida, ter no nosso programa um `makeCommand` analisando-o e inserindo-o na URLSession de forma adequada. O que temos aqui maximiza a legibilidade e a simplicidade sem enfocar na facilidade de uso.
## Enviando uma Transação
Como de costume, o envio de uma transação (da maneira mais difícil) é um processo de várias etapas:
0. Gerar ou receber um endereço de recebimento;
1. Encontrar um UTXO não gasto;
2. Criar uma transação bruta;
3. Assinar a transação bruta;
4. Enviar a transação bruta.
Usando o `address` gerado na etapa anterior como nosso destinatário.
### 1. Encontrando um UTXO Não Gasto
O RPC `listunspent` permite que encontremos nosso UTXO:
```
method = "listunspent"
param = ""
makeCommand(method: method,param: param) { result in
let unspent = result as! NSArray
let utxo = unspent[0] as! NSDictionary
let txid = utxo["txid"] as! NSString
let vout = utxo["vout"] as! NSInteger
let amount = utxo["amount"] as! NSNumber
let new_amount = amount.floatValue - 0.0001
```
Como em outros exemplos, vamos arbitrariamente pegar o enésimo UTXO e pegar o `txid`, `vout` e `amount` dele.
> :information_source **NOTA:** Mais uma vez, um programa real seria muito mais sofisticado.
### 2. Criando uma Transação Bruta
Criar uma transação bruta é a coisa mais complicada, porque precisamos acertar todos os nossos objetos JSON, arrays e aspas. Veja como fazer isso no Swift, usando a formatação `param` muito básica do transmissor:
```
method = "createrawtransaction"
param="[ { \"txid\": \"\(txid)\", \"vout\": \(vout) } ], { \"\(address)\": \(new_amount)}"
makeCommand(method: method,param: param) { result in
let hex = result as! NSString
```
### 3. Assinando a Transação Bruta
Assinar nossa transação requer apenas que executemos o RPC `signrawtransactionwithwallet`, usando nosso novo `hex`:
```
method = "signrawtransactionwithwallet"
param = "\"\(hex)\""
makeCommand(method: method,param: param) { result in
let signedhexinfo = result as! NSDictionary
let signedhex = signedhexinfo["hex"] as! NSString
```
### 4. Enviando a Transação Bruta
Enviar nossa transação é igualmente simples:
```
method = "sendrawtransaction"
param = "\"\(signedhex)\""
makeCommand(method: method,param: param) { result in
let new_txid = result as! NSString
print("TXID: \(new_txid)")
}
}
}
}
}
```
O código para este remetente de transação pode ser encontrado no [diretório src/](../src/18_6_sendtx.playground).
## Usando o Swift de Outras Maneiras
Isso cobre nossas discussões habituais sobre a programação do Bitcoin RPC usando uma linguagem, mas o Swift é uma linguagem particularmente importante, pois pode ser implantada em dispositivos móveis, um dos principais locais para nossas carteiras. Como tal, podemos querer considerar algumas outras bibliotecas:
* O [framework ios-Bitcoin](https://github.com/BlockchainCommons/iOS-Bitcoin) da Blockchain Commons converte a biblioteca Libbitcoin de C++ para Swift;
* [Libwally Swift](https://github.com/blockchain/libwally-swift) é um wrapper Swift para a Libwally.
## Resumo: Acessando o Bitcoind com Swift
O Swift é uma linguagem de programação robusta e moderna que infelizmente ainda não tem nenhuma biblioteca RPC fácil de ser utilizada... o que acabou de nos dar a oportunidade de escrever uma função de acesso ao RPC. Com isso em mãos, podemos interagir com o `bitcoind` em um Mac ou criar aplicativos complementares em um iPhone, o que é uma combinação perfeita para usar o Bitcoin com airgap.
## O Que Vem Depois?
Aprenda sobre o Lightning em [Capítulo 19: Compreendendo Nossa Configuração da Lightning](19_0_Understanding_Your_Lightning_Setup.md).
## Variante: Implantando o Swift no Ubuntu
Se preferirmos implantar o Swift no Ubuntu, podemos fazê-lo, embora a funcionalidade não seja a mesma. Parte do código neste capítulo provavelmente gerará erros que precisaremos resolver e também precisaremos trabalhar mais para vincular as bibliotecas C.
Para começar, vamos instalar algumas bibliotecas Debian necessárias:
```
$ sudo apt-get install clang
$ sudo apt-get install libcurl4 libpython2.7 libpython2.7-dev
```
Se estivermos usando o Debian 10 ou superior (e realmente deveríamos estar usando), também precisaremos retroagir algumas bibliotecas para obter as versões mais antigas:
```
$ sudo apt-get install libtinfo5 libncurses5
```
Posteriormente, podemos baixar e instalar o Swift:
```
$ wget https://swift.org/builds/swift-5.1.3-release/ubuntu1804/swift-5.1.3-RELEASE/swift-5.1.3-RELEASE-ubuntu18.04.tar.gz
$ tar xzfv swift-5.1.3-RELEASE-ubuntu18.04.tar.gz
$ sudo mv swift-5.1.3-RELEASE-ubuntu18.04 /usr/share/swift
```
Para poder usar nossa nova configuração do Swift, precisaremos atualizar nosso `PATH` em nosso arquivo `.bashrc`:
```
$ echo "export PATH=/usr/share/swift/usr/bin:$PATH" >> ~/.bashrc
$ source ~/.bashrc
```
Agora podemos testar o Swift com o argumento `--version`:
```
$ swift --version
Swift version 5.1.3 (swift-5.1.3-RELEASE)
Target: x86_64-unknown-linux-gnu
```
### Criando um Projeto
Depois de instalar o Swift em nossa máquina Ubuntu, podemos criar projetos com o comando `package init`:
```
$ mkdir swift-project
$ cd swift-project/
/swift-project$ swift package init --type executable
Creating executable package: swift-project
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/swift-project/main.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/swift-projectTests/
Creating Tests/swift-projectTests/swift_projectTests.swift
Creating Tests/swift-projectTests/XCTestManifests.swift
```
Também editaremos o `Sources/.../main.swift` e, quando estivermos pronto para compilar, podemos usar o comando `build`:
```
$ swift build
[4/4] Linking swift-project
```
Finalmente, seremos capazes de executar o programa a partir do diretório `.build/debug`:
```
$ .build/debug/swift-project
Hello, world!
```
Boa sorte!

View File

@ -0,0 +1,26 @@
# Capítulo 19: Compreendendo Nossa Configuração da Lightning
> :information_source: **NOTA:** Este é um rascunho que está em andamento. Seu objetivo é que possa obter alguns comentários dos revisores iniciais. Ainda não está pronto para ser produzido.
O capítulo anterior concluiu nosso trabalho com o Bitcoin propriamente dito, por meio do CLI, scripts e linguagens de programação. No entanto, existem muitos outros utilitários dentro do ecossistema Bitcoin. Neste capítulo e no próximo, iremos cobrir o que pode ser o maior e mais importante deles, a Lightning Network. Aqui, começaremos a trabalhar com a interface de linha de comando `lightning-cli`, entendendo a configuração do c-lightning e dos seus recursos, incluindo alguns exemplos e configuração básica.
## Objetivos Deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Avaliar se um node c-lightning está instalado e atualizado;
* Executar comandos básicos de uma carteira Lightning;
* Criar um canal na Lightning.
Os objetivos secundários do capítulo incluem a capacidade de:
* Compreender a configuração básica da Lightning;
* Compreender a interação dos canais Lightning;
* Entender como usar a Lightning.
## Tabela de Conteúdo
* [Seção 1: Verificando Nossa Configuração da c-lightning](19_1_Verifying_Your_Lightning_Setup.md)
* [Seção 2: Conhecendo Nossa Configuração da c-lightning](19_2_Knowing_Your_lightning_Setup.md)
* [Adendo: Acessando um Segundo Node Lightning](19_2__Interlude_Accessing_a_Second_Lightning_Node.md)
* [Seção 3: Criando um Canal Lightning](19_3_Setting_Up_a_Channel.md)

View File

@ -0,0 +1,288 @@
# 19.1: Verificando Nossa Configuração da c-lightning
>: information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Nesta seção, instalaremos e verificaremos a c-lightning, nosso utilitário para acessar a Lightning Network.
> :book: ***O que é a Lightning Network?*** A Rede Lightning é uma rede descentralizada que usa a funcionalidade de contrato inteligente da blockchain do Bitcoin para permitir pagamentos instantâneos em uma rede de participantes. A Lightning é construída como um protocolo de segunda camada que interage com o Bitcoin para permitir que os usuários troquem seus bitcoins "fora da blockchain" (ou o jargão em inglês, "off-chain").
> :book: ***O que é um protocolo de segunda camada?*** A segunda camada refere-se a um protocolo secundário criado em cima do sistema de blockchain do Bitcoin. O objetivo principal desses protocolos é resolver a velocidade de transação e as dificuldades de escala que estão presentes no Bitcoin. O Bitcoin não é capaz de processar milhares de transações por segundo (TPS), então protocolos de segunda camada foram criados para resolver o problema de escalabilidade da blockchain. Essas soluções também são conhecidas como soluções de dimensionamento "off-chain".
## Instalando a c-lightning
Se já usamos os [Bitcoin Standup Scripts](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts), talvez já o tenhamos instalado no início deste curso. Podemos testar isto verificando se o `lightningd` está em execução:
```
$ ps auxww | grep -i lightning
standup 31213 0.0 0.2 24144 10424 pts/0 S 15:38 0:00 lightningd --testnet
standup 31214 0.0 0.1 22716 7444 pts/0 S 15:38 0:00 /usr/local/bin/../libexec/c-lightning/plugins/autoclean
standup 31215 0.0 0.2 22992 8248 pts/0 S 15:38 0:00 /usr/local/bin/../libexec/c-lightning/plugins/bcli
standup 31216 0.0 0.1 22756 7604 pts/0 S 15:38 0:00 /usr/local/bin/../libexec/c-lightning/plugins/keysend
standup 31217 0.0 0.1 22776 7648 pts/0 S 15:38 0:00 /usr/local/bin/../libexec/c-lightning/plugins/pay
standup 31218 0.0 0.1 22720 7652 pts/0 S 15:38 0:00 /usr/local/bin/../libexec/c-lightning/plugins/txprepare
standup 31219 0.0 0.1 22744 7716 pts/0 S 15:38 0:00 /usr/local/bin/../libexec/c-lightning/plugins/spenderp
standup 31227 0.0 0.1 22748 7384 pts/0 SL 15:38 0:00 /usr/local/libexec/c-lightning/lightning_hsmd
standup 31228 0.0 0.2 23044 8192 pts/0 S 15:38 0:00 /usr/local/libexec/c-lightning/lightning_connectd
standup 31229 0.0 0.1 22860 7556 pts/0 S 15:38 0:00 /usr/local/libexec/c-lightning/lightning_gossipd
standup 32072 0.0 0.0 6208 888 pts/0 S+ 15:50 0:00 grep -i lightning
```
Caso contrário, precisaremos instalá-lo agora. Infelizmente, se estivermos usando o Debian, precisaremos instalá-lo manualmente, compilando o código-fonte, mas ainda assim deve ser muito simples se seguirmos estas instruções. Se acontecer de estarmos em um sistema Ubuntu padrão, podemos tentar [Instalar a partir do Ubuntu ppa](#variant-install-from-ubuntu-ppa), e sempre podemos tentar [Instalar os binários pré-compilados](#variant-install-pre-compiled-binaries).
> :book: ***O que é a c-lightning?*** Existem três implementações diferentes da Lightning no momento: C-lightning, LND e Eclair. Todos devem ser funcionalmente compatíveis, com base nas mesmas [RFCs do BOLT](https://github.com/lightningnetwork/lightning-rfc/blob/master/00-introduction.md), mas os detalhes de implementação podem ser diferentes. Escolhemos a c-lightning como base do curso porque ela também faz parte do [projeto Elements](https://github.com/ElementsProject), que contém a Libwally.
### Compilando o Código-Fonte da c-lightning
A instalação da Lightning a partir do código-fonte deve ser bem simples se seguirmos estas instruções.
_Provavelmente_ desejaremos fazer isso em um node não prunado, pois trabalhar com nodes prunados na Lightning pode causar problemas de instalação e uso. Se, no início deste curso, configuramos nosso node para ser prunado, podemos querer substituí-lo por um full node agora. Se estivermos usando a testnet, provavelmente conseguiremos usar o mesmo tipo de máquina que usamos para o node prunado.
> :warning: **AVISO:** Realmente podemos executar a c-lightning em um node prunado. No entanto, conforme observamos no [repositório Lightning](https://github.com/ElementsProject/lightning#pruning), pode haver uma série de problemas. Para fazer isso funcionar, devemos garantir que o node da Lightning sempre tente atualizar informações sobre os blocos que o node do Bitcoin não excluiu. Para fazermos isso, devemos nos certificar de que (1) nosso node de Bitcoin está totalmente atualizado antes de iniciar nosso node da Lightning pela primeira vez e; (2) nosso node Lightning nunca fique defasado do node do Bitcoin (para um node prunado em 550 blocos padrão, ele nunca pode ser desligado por 4 dias ou mais). Portanto, podemos usar o node assim, mas apresenta algum perigo, o que não é uma boa ideia se estivermos executando um serviço em produção.
Dito isso, estamos prontos para instalar a Lightning:
Primeiro, vamos instalar as dependências, incluindo requisitos de desenvolvimento.
```
$ sudo apt-get install -y \
autoconf automake build-essential git libtool libgmp-dev \
libsqlite3-dev python3 python3-mako net-tools zlib1g-dev libsodium-dev \
gettext
$ sudo apt-get install -y valgrind python3-pip libpq-dev
```
Isso pode demorar um pouco, porque há várias dependências e algumas são bem grandes.
Em segundo lugar, vamos clonar o repositório Lightning:
```
$ cd ~
$ git clone https://github.com/ElementsProject/lightning.git
$ cd lightning
```
Agora podemos usar o `pip3` que instalamos para instalar requisitos adicionais para a compilação e posteriomente configurar tudo:
```
$ pip3 install -r requirements.txt
$ ./configure
```
Agora, vamos compilar. Isso pode levar algum tempo também, dependendo do processamento da nossa máquina.
```
$ make
```
Depois disso, o que precisamos fazer é instalar:
```
$ sudo make install
```
## Verificando Nossa Instalação
Podemos confirmar que o lightningd foi instalado corretamente usando o parâmetro `help`:
```
$ lightningd --help
lightningd: WARNING: default network changing in 2020: please set network=testnet in config!
Usage: lightningd
A bitcoin lightning daemon (default values shown for network: testnet).
--conf=<file> Specify configuration file
--lightning-dir=<dir> Set base directory: network-specific
subdirectory is under here
(default: "/home/javier/.lightning")
--network <arg> Select the network parameters (bitcoin,
testnet, regtest, litecoin or
litecoin-testnet) (default: testnet)
--testnet Alias for --network=testnet
--signet Alias for --network=signet
--mainnet Alias for --network=bitcoin
```
## Executando lightningd
Começaremos a explorar a Lightning Network com o comando `lightning-cli`. No entanto, `lightningd` _deve_ estar rodando para podermos usar o `lightning-cli`, já que `lightning-cli` envia comandos JSON-RPC para o `lightningd` (tudo exatamente como o `bitcoin-cli` e o `bitcoind`).
Se instalamos a `c-lightning` manualmente, precisaremos iniciá-la:
```
$ nohup lightningd --testnet &
```
### Executando o lightningd como um serviço
Se preferirmos, podemos instalar o `lightningd` como um serviço que será executado toda vez que reiniciarmos nossa máquina. Os comandos seguintes farão isso e ele começará a funcionar imediatamente:
```
$ cat > ~/lightningd.service << EOF
# It is not recommended to modify this file in-place, because it will
# be overwritten during package upgrades. If you want to add further
# options or overwrite existing ones then use
# $ systemctl edit bitcoind.service
# See "man systemd.service" for details.
# Note that almost all daemon options could be specified in
# /etc/lightning/config, except for those explicitly specified as arguments
# in ExecStart=
[Unit]
Description=c-lightning daemon
[Service]
ExecStart=/usr/local/bin/lightningd --testnet
# Process management
####################
Type=simple
PIDFile=/run/lightning/lightningd.pid
Restart=on-failure
# Directory creation and permissions
####################################
# Run as standup
User=standup
# /run/lightningd
RuntimeDirectory=lightningd
RuntimeDirectoryMode=0710
# Hardening measures
####################
# Provide a private /tmp and /var/tmp.
PrivateTmp=true
# Mount /usr, /boot/ and /etc read-only for the process.
ProtectSystem=full
# Disallow the process and all of its children to gain
# new privileges through execve().
NoNewPrivileges=true
# Use a new /dev namespace only populated with API pseudo devices
# such as /dev/null, /dev/zero and /dev/random.
PrivateDevices=true
# Deny the creation of writable and executable memory mappings.
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.target
EOF
$ sudo cp ~/lightningd.service /etc/systemd/system
$ sudo systemctl enable lightningd.service
$ sudo systemctl start lightningd.service
```
### Habilitando Conexões Remotas
Se tivermos algum tipo de firewall, precisaremos abrir a porta 9735 para permitir que outros nodes da Lightning interajam conosco.
Se usarmos o `ufw` do Bitcoin Standup, podemos fazer da seguinte maneira:
```
$ sudo ufw allow 9735
```
## Verificando o Nosso Node
Podemos verificar se o nosso node Lightning está pronto para funcionar comparando a saída de `bitcoin-cli getblockcount` com o resultado de `blockheight` do `lightning-cli getinfo`.
```
$ bitcoin-cli -testnet getblockcount
1838587
$ lightning-cli --testnet getinfo
{
"id": "03d4592f1244cd6b5a8bb7fba6a55f8a91591d79d3ea29bf8e3c3a405d15db7bf9",
"alias": "HOPPINGNET",
"color": "03d459",
"num_peers": 0,
"num_pending_channels": 0,
"num_active_channels": 0,
"num_inactive_channels": 0,
"address": [
{
"type": "ipv4",
"address": "74.207.240.32",
"port": 9735
},
{
"type": "ipv6",
"address": "2600:3c01::f03c:92ff:fe48:9ddd",
"port": 9735
}
],
"binding": [
{
"type": "ipv6",
"address": "::",
"port": 9735
},
{
"type": "ipv4",
"address": "0.0.0.0",
"port": 9735
}
],
"version": "v0.9.1-96-g6f870df",
"blockheight": 1838587,
"network": "testnet",
"msatoshi_fees_collected": 0,
"fees_collected_msat": "0msat",
"lightning-dir": "/home/standup/.lightning/testnet"
}
```
Neste caso, o `blockheight` é mostrado como `1838587` por ambos os comandos.
Em vez disso, podemos obter um erro, dependendo da situação.
Se o node Bitcoin ainda estiver sincronizando com a rede, devemos ver uma mensagem como esta:
```
"warning_bitcoind_sync": "Bitcoind is not up-to-date with network."
```
Se o nosso node Lightning não estiver atualizado, receberemos uma mensagem como esta:
```
"warning_lightningd_sync": "Still loading latest blocks from bitcoind."
```
Se tentarmos executar em uma blockchain prunada cujo node Bitcoin não estava atualizado quando iniciamos o node Lightning, receberemos mensagens de erro em nosso log parecidas com esta:
```
bitcoin-cli -testnet getblock 0000000000000559febee77ab6e0be1b8d0bef0f971c7a4bee9785393ecef451 0 exited with status 1
```
## Criando Aliases
Sugerimos a criação de alguns aliases (apelidos de comandos) para facilitar o uso da c-lightning.
Podemos fazer isso colocando-os em nosso arquivo `.bash_profile`.
```
cat >> ~/.bash_profile <<EOF
alias lndir="cd ~/.lightning/" #linux default c-lightning path
alias lnc="lightning-cli"
alias lnd="lightningd"
alias lninfo='lightning-cli getinfo'
EOF
```
Depois de inserir esses aliases, podemos executar o comando `source ~/.bash_profile` para inseri-los, ou apenas efetuar logout e login novamente.
Podemos observar que esses aliases incluem atalhos para executar o `lightning-cli`, para executar o `lightningd` e para ir para o diretório c-lightning. Esses aliases têm como objetivo principal tornar nossa vida mais fácil. Sugerimos criar outros apelidos para facilitar o uso de comandos frequentes (e seus argumentos) e para minimizar erros. Os aliases desse tipo podem ser ainda mais úteis se tivermos uma configuração complexa onde regularmente executamos comandos associados a Mainnet, com Testnet _e_ com a Regtest, conforme explicado mais adiante.
Dito isso, o uso desses aliases _neste_ livro pode acidentalmente obscurecer as lições principais que estão sendo ensinadas sobre a c-lightning, portanto, continuaremos a mostrar os comandos completos. Podemos ajustá-los para nosso próprio uso conforme apropriado.
## Opcional: Modificando Nossos Tipos de Servidor
> :link: **TESTNET vs MAINNET:** Ao configurar nosso node, escolhemos criá-lo como um node Mainnet, Testnet ou Regtest. Embora este documento presuma uma configuração no Testenet, vale a pena entender como podemos acessar e usar os outros tipos de configuração, mesmo todos estando na mesma máquina! Mas, se você for um usuário iniciante, pode pular esta parte, pois não é necessária para uma configuração básica.
Quando o lightningd é inicializado, geralmente ele lê um arquivo de configuração cuja localização depende da rede que estamos usando (o padrão é `~/.lightning/testnet/config`). Isso pode ser alterado com os sinalizadores `conf` e `lightning-dir`.
```
~/.lightning/testnet$ ls -la config
-rw-rw-r-- 1 user user 267 jul 12 17:08 config
```
Também existe um arquivo de configuração geral (o padrão é `~/.lightning/config`). Se desejarmos executar vários tipos diferentes de nodes simultaneamente, devemos deixar o sinalizador testnet (ou regtest) fora deste arquivo de configuração. Devemos então escolher se estamos usando a mainnet, a testnet ou a regtest toda vez que executarmos o `lightningd` ou o `lightning-cli`.
Nossa configuração pode não ter nenhum arquivo de configuração: a c-lightning será executada com uma boa configuração padrão, sem eles.
## Resumo: Verificando Nossa Configuração da c-lightning
Antes de começar a brincar com a lightning, devemos nos certificar de que nossos aliases estão configurados, nosso `lightningd` está rodando e nosso node está sincronizado. Também podemos querer configurar algum acesso a configurações alternativas da Lightning, em outras redes.
## O Que Vem Depois?
Vamos continuar "Compreendendo a Configuração da Lightning" na seção [§19.2: Conhecendo Nossa Configuração da c-lightning](19_2_Knowing_Your_lightning_Setup.md).
## Variante: Instalando do Ubuntu ppa
Se estivermos usando uma versão do Ubuntu diferente do Debian, podemos instalar a c-lightning usando [Ubuntu ppa](https://launchpad.net/~lightningnetwork/+archive/ubuntu/ppa):
```
$ sudo apt-get install -y software-properties-common
$ sudo add-apt-repository -u ppa:lightningnetwork/ppa
$ sudo apt-get install lightningd
```
## Variante: Instalando Binários Pré-Compilados
Outro método para instalar a Lightning é usar os binários pré-compilados no [repositório Github](https://github.com/ElementsProject/lightning/releases). Vamos escolher o arquivo mais recente, como `clightning-v0.9.1-Ubuntu-20.04.tar.xz`.
Depois de baixá-lo, precisaremos ir para o diretório raiz e descompactá-lo:
```
$ cd /
$ sudo tar xf ~/clightning-v0.9.1-Ubuntu-20.04.tar.xz
```
Aviso: Isso exigirá que tenhamos exatamente as mesmas bibliotecas que foram usadas para criar o binário. Geralmente é mais fácil apenas recompilar.

View File

@ -0,0 +1,340 @@
# 19.2: Conhecendo Nossa Configuração da c-lightning
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Antes de começar a acessar a Lightning Network, devemos compreender melhor a nossa configuração.
## Conhecendo o Diretório da c-lightning
Ao usar a c-lightning, tudo será mantindo dentro do diretório `~/.lightning`.
O diretório principal contém apenas os diretórios para as redes configuradas, neste caso da Testnet:
```
$ ls ~/.lightning
testnet
```
O diretório `~/.lightning/testnet` irá então conter a essência da nossa configuração:
```
$ ls ~/.lightning/testnet3
config gossip_store hsm_secret lightningd.sqlite3 lightningd.sqlite3-journal lightning-rpc
```
> :link: **TESTNET vs MAINNET:** Se estivermos usando a Mainnet, então _tudo_ será colocado no diretório principal `~/.lightning/bitcoin`. Essas várias configurações _empilham-se_ elegantemente, então se estivermos usando a Mainnet, Testnet e Regtest, descobriremos que `~/.lightning/bitcoin` contém os arquivos de configuração e os dados da Mainnet, o diretório `~/.lightning/testnet` contém os dados da Testnet, e o diretório `~/.lightning/regtest` contém os dados Regtest.
## Conhecendo os Comandos lightning-cli
A maior parte do nosso trabalho inicial será feito com o comando `lightning-cli`, que oferece uma interface fácil para o `lightningd`, assim como o `bitcoin-cli`.
Já vimos que o comando `help` nos dará uma lista de outros comandos:
```
$ lightning-cli help
lightning-cli: WARNING: default network changing in 2020: please set network=testnet in config!
=== bitcoin ===
feerates style
Return feerate estimates, either satoshi-per-kw ({style} perkw) or satoshi-per-kb ({style} perkb).
newaddr [addresstype]
Get a new {bech32, p2sh-segwit} (or all) address to fund a channel (default is bech32)
reserveinputs outputs [feerate] [minconf] [utxos]
Reserve inputs and pass back the resulting psbt
sendpsbt psbt
Finalize, extract and send a PSBT.
signpsbt psbt
Sign this wallet's inputs on a provided PSBT.
txdiscard txid
Abandon a transaction created by txprepare
txprepare outputs [feerate] [minconf] [utxos]
Create a transaction, with option to spend in future (either txsend and txdiscard)
txsend txid
Sign and broadcast a transaction created by txprepare
unreserveinputs psbt
Unreserve inputs, freeing them up to be reused
withdraw destination satoshi [feerate] [minconf] [utxos]
Send to {destination} address {satoshi} (or 'all') amount via Bitcoin transaction, at optional {feerate}
=== channels ===
close id [unilateraltimeout] [destination] [fee_negotiation_step]
Close the channel with {id} (either peer ID, channel ID, or short channel ID). Force a unilateral close after {unilateraltimeout} seconds (default 48h). If {destination} address is provided, will be used as output address.
fundchannel_cancel id
Cancel inflight channel establishment with peer {id}.
fundchannel_complete id txid txout
Complete channel establishment with peer {id} for funding transactionwith {txid}. Returns true on success, false otherwise.
fundchannel_start id amount [feerate] [announce] [close_to] [push_msat]
Start fund channel with {id} using {amount} satoshis. Returns a bech32 address to use as an output for a funding transaction.
getroute id msatoshi riskfactor [cltv] [fromid] [fuzzpercent] [exclude] [maxhops]
Show route to {id} for {msatoshi}, using {riskfactor} and optional {cltv} (default 9). If specified search from {fromid} otherwise use this node as source. Randomize the route with up to {fuzzpercent} (default 5.0). {exclude} an array of short-channel-id/direction (e.g. [ '564334x877x1/0', '564195x1292x0/1' ]) or node-id from consideration. Set the {maxhops} the route can take (default 20).
listchannels [short_channel_id] [source]
Show channel {short_channel_id} or {source} (or all known channels, if not specified)
listforwards
List all forwarded payments and their information
setchannelfee id [base] [ppm]
Sets specific routing fees for channel with {id} (either peer ID, channel ID, short channel ID or 'all'). Routing fees are defined by a fixed {base} (msat) and a {ppm} (proportional per millionth) value. If values for {base} or {ppm} are left out, defaults will be used. {base} can also be defined in other units, for example '1sat'. If {id} is 'all', the fees will be applied for all channels.
=== network ===
connect id [host] [port]
Connect to {id} at {host} (which can end in ':port' if not default). {id} can also be of the form id@host
disconnect id [force]
Disconnect from {id} that has previously been connected to using connect; with {force} set, even if it has a current channel
listnodes [id]
Show node {id} (or all, if no {id}), in our local network view
listpeers [id] [level]
Show current peers, if {level} is set, include logs for {id}
ping id [len] [pongbytes]
Send peer {id} a ping of length {len} (default 128) asking for {pongbytes} (default 128)
=== payment ===
createonion hops assocdata [session_key]
Create an onion going through the provided nodes, each with its own payload
decodepay bolt11 [description]
Decode {bolt11}, using {description} if necessary
delexpiredinvoice [maxexpirytime]
Delete all expired invoices that expired as of given {maxexpirytime} (a UNIX epoch time), or all expired invoices if not specified
delinvoice label status
Delete unpaid invoice {label} with {status}
invoice msatoshi label description [expiry] [fallbacks] [preimage] [exposeprivatechannels]
Create an invoice for {msatoshi} with {label} and {description} with optional {expiry} seconds (default 1 week), optional {fallbacks} address list(default empty list) and optional {preimage} (default autogenerated)
listinvoices [label]
Show invoice {label} (or all, if no {label})
listsendpays [bolt11] [payment_hash]
Show sendpay, old and current, optionally limiting to {bolt11} or {payment_hash}.
listtransactions
List transactions that we stored in the wallet
sendonion onion first_hop payment_hash [label] [shared_secrets] [partid]
Send a payment with a pre-computed onion.
sendpay route payment_hash [label] [msatoshi] [bolt11] [payment_secret] [partid]
Send along {route} in return for preimage of {payment_hash}
waitanyinvoice [lastpay_index] [timeout]
Wait for the next invoice to be paid, after {lastpay_index} (if supplied). If {timeout} seconds is reached while waiting, fail with an error.
waitinvoice label
Wait for an incoming payment matching the invoice with {label}, or if the invoice expires
waitsendpay payment_hash [timeout] [partid]
Wait for payment attempt on {payment_hash} to succeed or fail, but only up to {timeout} seconds.
=== plugin ===
autocleaninvoice [cycle_seconds] [expired_by]
Set up autoclean of expired invoices.
estimatefees
Get the urgent, normal and slow Bitcoin feerates as sat/kVB.
fundchannel id amount [feerate] [announce] [minconf] [utxos] [push_msat]
Fund channel with {id} using {amount} (or 'all'), at optional {feerate}. Only use outputs that have {minconf} confirmations.
getchaininfo
Get the chain id, the header count, the block count, and whether this is IBD.
getrawblockbyheight height
Get the bitcoin block at a given height
getutxout txid vout
Get informations about an output, identified by a {txid} an a {vout}
listpays [bolt11]
List result of payment {bolt11}, or all
pay bolt11 [msatoshi] [label] [riskfactor] [maxfeepercent] [retry_for] [maxdelay] [exemptfee]
Send payment specified by {bolt11} with {amount}
paystatus [bolt11]
Detail status of attempts to pay {bolt11}, or all
plugin subcommand=start|stop|startdir|rescan|list
Control plugins (start, stop, startdir, rescan, list)
sendrawtransaction tx
Send a raw transaction to the Bitcoin network.
=== utility ===
check command_to_check
Don't run {command_to_check}, just verify parameters.
checkmessage message zbase [pubkey]
Verify a digital signature {zbase} of {message} signed with {pubkey}
getinfo
Show information about this node
getlog [level]
Show logs, with optional log {level} (info|unusual|debug|io)
getsharedsecret point
Compute the hash of the Elliptic Curve Diffie Hellman shared secret point from this node private key and an input {point}.
help [command]
List available commands, or give verbose help on one {command}.
listconfigs [config]
List all configuration options, or with [config], just that one.
listfunds
Show available funds from the internal wallet
signmessage message
Create a digital signature of {message}
stop
Shut down the lightningd process
waitblockheight blockheight [timeout]
Wait for the blockchain to reach {blockheight}, up to {timeout} seconds.
=== developer ===
dev-listaddrs [bip32_max_index]
Show addresses list up to derivation {index} (default is the last bip32 index)
dev-rescan-outputs
Synchronize the state of our funds with bitcoind
---
run `lightning-cli help <command>` for more information on a specific command
```
## Conhecendo Informações da Lightning
Uma variedade de comandos `lightning-cli` podem fornecer informações adicionais sobre nosso node Lightning. Os mais comuns são:
```
$ lightning-cli --testnet listconfigs
$ lightning-cli --testnet listfunds
$ lightning-cli --testnet listtransactions
$ lightning-cli --testnet listinvoices
$ lightning-cli --testnet listnodes
```
* listconfigs: O comando RPC `listconfigs` lista todas as opções de configuração;
* listfunds: O comando RPC `listfunds` exibe todos os fundos disponíveis, seja em saídas não gastas (UTXOs) na carteira interna ou fundos bloqueados em canais abertos no momento;
* listtransactions: O comando RPC `listtransactions` retorna as transações rastreadas na carteira. Isso inclui depósitos, retiradas e transações relacionadas a canais;
* listinvoices: O comando RPC `listinvoices` recupera o status de um invoice específico, se houver, ou o status de todos os invoices, se não houver nenhum argumento;
* listnodes: O comando RPC `listnodes` retorna nodes que nosso servidor aprendeu através da comunicação com outros nodes, ou um específico se o id do node foi informado.
Por exemplo, `lightning-cli listconfigs` fornece uma variedade de informações sobre nossa configuração:
```
c$ lightning-cli --testnet listconfigs
{
"# version": "v0.8.2-398-g869fa08",
"lightning-dir": "/home/standup/.lightning",
"network": "testnet",
"allow-deprecated-apis": true,
"rpc-file": "lightning-rpc",
"plugin": "/usr/local/bin/../libexec/c-lightning/plugins/fundchannel",
"plugin": "/usr/local/bin/../libexec/c-lightning/plugins/autoclean",
"plugin": "/usr/local/bin/../libexec/c-lightning/plugins/bcli",
"plugin": "/usr/local/bin/../libexec/c-lightning/plugins/pay",
"plugin": "/usr/local/bin/../libexec/c-lightning/plugins/keysend",
"plugins": [
{
"path": "/usr/local/bin/../libexec/c-lightning/plugins/fundchannel",
"name": "fundchannel"
},
{
"path": "/usr/local/bin/../libexec/c-lightning/plugins/autoclean",
"name": "autoclean",
"options": {
"autocleaninvoice-cycle": null,
"autocleaninvoice-expired-by": null
}
},
{
"path": "/usr/local/bin/../libexec/c-lightning/plugins/bcli",
"name": "bcli",
"options": {
"bitcoin-datadir": null,
"bitcoin-cli": null,
"bitcoin-rpcuser": null,
"bitcoin-rpcpassword": null,
"bitcoin-rpcconnect": null,
"bitcoin-rpcport": null,
"bitcoin-retry-timeout": null,
"commit-fee": "500"
}
},
{
"path": "/usr/local/bin/../libexec/c-lightning/plugins/pay",
"name": "pay"
},
{
"path": "/usr/local/bin/../libexec/c-lightning/plugins/keysend",
"name": "keysend"
}
],
"disable-plugin": [],
"always-use-proxy": false,
"daemon": "false",
"wallet": "sqlite3:///home/user/.lightning/testnet/lightningd.sqlite3",
"wumbo": false,
"wumbo": false,
"rgb": "03fce2",
"alias": "learningBitcoin",
"pid-file": "/home/user/.lightning/lightningd-testnet.pid",
"ignore-fee-limits": false,
"watchtime-blocks": 144,
"max-locktime-blocks": 720,
"funding-confirms": 3,
"commit-fee-min": 200,
"commit-fee-max": 2000,
"cltv-delta": 6,
"cltv-final": 10,
"commit-time": 10,
"fee-base": 1,
"rescan": 15,
"fee-per-satoshi": 10,
"max-concurrent-htlcs": 483,
"min-capacity-sat": 10000,
"offline": "false",
"autolisten": true,
"disable-dns": "false",
"enable-autotor-v2-mode": "false",
"encrypted-hsm": false,
"rpc-file-mode": "0600",
"log-level": "DEBUG",
"log-prefix": "lightningd"
}
```
## Resumo: Conhecendo Nossa Configuração da c-lightning
O diretório `~/.lightning` contém todos os arquivos, enquanto o comando `lightning-cli help` mostra uma variedade de informações dos comandos que podem ser usados para obter mais informações sobre a configuração e o funcionamento da Lightning Network.
## O Que Vem Depois?
Precisaremos de um segundo node para testar o pagamento dos invoices. Se precisarmos de suporte para configurar um, podemos ler o [Prefácio: Acessando um Segundo Node Lightning](19_2__Interlude_Accessing_a_Second_Lightning_Node.md).
Caso contrário, vamos continuar "Compreendendo a Configuração da Lightning" na seção [§19.3: Criando um Canal na Lightning](19_3_Setting_Up_a_Channel.md).

View File

@ -0,0 +1,326 @@
# Prefácio: Acessando um Segundo Node Lightning
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Quando estávamos brincando com o Bitcoin, estávamos acessando uma rede existente, e isso torna tudo relativamente fácil para se trabalhar. Apenas ligávamos o `bitcoind` e estávamos imediatamente interagindo com a rede. Agora, a Lightning funciona da seguinte maneira: é fundamentalmente uma rede ponto a ponto, construída a partir das conexões entre dois nodes individuais. Em outras palavras, para interagir com a Lightning Network, precisaremos primeiro encontrar um node ao qual podemos nos conectar.
Existem quatro maneiras de fazermos isso (das quais as três primeiras são possíveis para a nossa primeira conexão):
## Pedindo Informações Sobre um Node
Se outra pessoa já tiver um node da Lightning Network na rede que escolhemos, podemos pedir o ID dele.
Se estiverem executando a c-lightning, eles só precisam usar o comando `getinfo`:
```
$ lightning-cli getinfo
lightning-cli: WARNING: default network changing in 2020: please set network=testnet in config!
"id": "03240a4878a9a64aea6c3921a434e573845267b86e89ab19003b0c910a86d17687",
"alias": "VIOLETGLEE",
"color": "03240a",
"num_peers": 0,
"num_pending_channels": 0,
"num_active_channels": 0,
"num_inactive_channels": 0,
"address": [
{
"type": "ipv4",
"address": "74.207.240.32",
"port": 9735
}
],
"binding": [
{
"type": "ipv6",
"address": "::",
"port": 9735
},
{
"type": "ipv4",
"address": "0.0.0.0",
"port": 9735
}
],
"version": "v0.9.1-96-g6f870df",
"blockheight": 1862854,
"network": "testnet",
"msatoshi_fees_collected": 0,
"fees_collected_msat": "0msat",
"lightning-dir": "/home/standup/.lightning/testnet"
}
```
Eles poderão então nos dizer o `ID` deles (`03240a4878a9a64aea6c3921a434e573845267b86e89ab19003b0c910a86d17687`). Eles também precisarão informar o endereço IP (`74.207.240.32`) e porta (`9735`).
## Criando um Novo Node c-lightning
No entanto, para fins de teste, provavelmente iremos desejar ter um segundo node sob nosso próprio controle. A maneira mais fácil de fazer isso é criar um segundo node c-lightning em uma nova máquina, usando Bitcoin Standup, de acordo com a seção [§2.1](02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md) ou compilando-o manualmente, de acordo com a seção [§19.1](19_1_Verifying_Your_Lightning_Setup.md).
Depois de ter nosso node em execução, podemos executar o `getinfo` para recuperar nossas informações, como mostrado acima.
## Criando um Novo Node LND
No entanto, para os exemplos do próximo capítulo, vamos criar um node LND. Isso nos permitirá demonstrar um pouco da profundidade do ecossistema Lightning, mostrando como comandos semelhantes funcionam nas duas plataformas diferentes.
Uma maneira de criar um node LND é executar os scripts Bitcoin Standup novamente em uma nova máquina, mas desta vez escolher a LND, de acordo com a seção [§2.1](2_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md).
Outra forma é compilar o LND a partir do código-fonte em uma máquina em que já estejamos executando um node Bitcoin, como falaremos abaixo.
### Compilando o Código-Fonte do LND
Primeiro, precisaremos baixar e instalar o Go:
```
$ wget --progress=bar:force https://dl.google.com/go/"go1.14.4"."linux"-"amd64".tar.gz -O ~standup/"go1.14.4"."linux"-"amd64".tar.gz
$ /bin/tar xzf ~standup/"go1.14.4"."linux"-"amd64".tar.gz -C ~standup
$ sudo mv ~standup/go /usr/local
```
Depois, precisamos nos certificar de que a versão Go é a mais atualizada (atualmente é a `go1.14.4`), e que a plataforma e arquitetura são adequadas para nossa máquina. O item acima funcionará para o Debian.
Vamos atualizar nosso PATH:
```
$ export GOPATH=~standup/gocode
$ export PATH="$PATH":/usr/local/go/bin:"$GOPATH"/bin
```
Em seguida, vamos nos certificar de que o `go` funciona:
```
$ go version
go version go1.14.4 linux/amd64
```
Também precisaremos do `git` e do `make`:
```
$ sudo apt-get install git
$ sudo apt-get install build-essential
```
Agora estamos prontos para recuperar o LND. Certifique-se de obter a versão atual (no momento, é a `v0.11.0-beta.rc4`).
```
$ go get -d github.com/lightningnetwork/lnd
```
E agora podemos compilar:
```
$ cd "$GOPATH"/src/github.com/lightningnetwork/lnd
$ git checkout v0.11.0-beta.rc4
$ make
$ make install
```
Os comandos acima irão instalar o Go na pasta `~/gocode/bin`, que é o `$GOPATH/bin`.
Devemos alterá-la para os diretórios globais:
```
$ sudo cp $GOPATH/bin/lnd $GOPATH/bin/lncli /usr/bin
```
### Criando um Arquivo de Configuração do LND
Ao contrário da c-lightning, precisaremos criar um arquivo de configuração padrão para o LND.
No entanto, primeiro, iremos precisar habilitar o ZMQ em nosso Bitcoind, se ainda não o fizemos na seção [§16.3](16_3_Receiving_Bitcoind_Notifications_with_C.md).
Isso requer adicionar o seguinte ao nosso arquivo `~/.bitcoin/bitcoin.conf`, se ainda não estiver lá:
```
zmqpubrawblock=tcp://127.0.0.1:28332
zmqpubrawtx=tcp://127.0.0.1:28333
```
Se estivermos usando um arquivo de configuração Bitcoin do Standup ou algum outro `conf` especializado, precisamos nos certificar de colocar nossos novos comandos na seção correta. Idealmente, devemos chegar perto do topo do arquivo, caso contrário, na seção `[test]` (assumindo, como de costume, que estamos usando a testnet).
Devemos então reiniciar o Bitcoin (ou apenas reiniciar nossa máquina). Podemos testar se está tudo funcionando da seguinte maneira:
```
$ 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
}
]
```
Agora estamos prontos para criar um arquivo de configuração.
Primeiro, precisamos recuperar nosso rpcuser e rpcpassword. A seguinte é uma maneira automatizada de fazer isso:
```
$ BITCOINRPC_USER=$(cat ~standup/.bitcoin/bitcoin.conf | grep rpcuser | awk -F = '{print $2}')
$ BITCOINRPC_PASS=$(cat ~standup/.bitcoin/bitcoin.conf | grep rpcpassword | awk -F = '{print $2}')
```
> :warning: **AVISO:** Obviamente, nunca iremos armazenar nossa senha RPC em uma variável shell em um ambiente de produção.
Em seguida, podemos gravar o arquivo:
```
$ mkdir ~/.lnd
$ cat > ~/.lnd/lnd.conf << EOF
[Application Options]
maxlogfiles=3
maxlogfilesize=10
#externalip=1.1.1.1 # change to your public IP address if required.
alias=StandUp
listen=0.0.0.0:9735
debuglevel=debug
[Bitcoin]
bitcoin.active=1
bitcoin.node=bitcoind
bitcoin.testnet=true
[Bitcoind]
bitcoind.rpchost=localhost
bitcoind.rpcuser=$BITCOINRPC_USER
bitcoind.rpcpass=$BITCOINRPC_PASS
bitcoind.zmqpubrawblock=tcp://127.0.0.1:28332
bitcoind.zmqpubrawtx=tcp://127.0.0.1:28333
EOF
```
### Criando um Serviço LND
Finalmente, podemos criar um serviço LND para executar automaticamente o `lnd`:
```
$ cat > ~/lnd.service << EOF
# It is not recommended to modify this file in-place, because it will
# be overwritten during package upgrades. If you want to add further
# options or overwrite existing ones then use
# $ systemctl edit lnd.service
# See "man systemd.service" for details.
# Note that almost all daemon options could be specified in
# /etc/lnd/lnd.conf, except for those explicitly specified as arguments
# in ExecStart=
[Unit]
Description=LND Lightning Network Daemon
Requires=bitcoind.service
After=bitcoind.service
[Service]
ExecStart=/usr/bin/lnd
ExecStop=/usr/bin/lncli --lnddir /var/lib/lnd stop
PIDFile=/run/lnd/lnd.pid
User=standup
Type=simple
KillMode=process
TimeoutStartSec=60
TimeoutStopSec=60
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
EOF
```
Em seguida, precisaremos instalar aquilo e iniciar as coisas:
```
$ sudo cp ~/lnd.service /etc/systemd/system
$ sudo systemctl enable lnd
$ sudo systemctl start lnd
```
(É esperado que a primeira vez leve um certo tempo.)
### Habilitando Conexões Remotas
Assim como na c-lightning, precisaremos tornar o LND acessível a outros nodes. Veja como fazer isso se usarmos o `ufw`, de acordo com as configurações do Bitcoin Standup:
```
$ sudo ufw allow 9735
```
### Criando uma Carteira
Na primeira vez que executamos o LND, devemos criar uma carteira:
```
$ lncli --network=testnet create
```
O LND pedirá uma senha e, em seguida, nos perguntará se desejaremos inserir um mnemônico existente (basta pressionar `n` para o último).
Agora devemos ter um `lnd` funcionando, que pode ser verificado com o comando `getinfo`:
```
$ lncli --network=testnet getinfo
{
"version": "0.11.0-beta.rc4 commit=v0.11.0-beta.rc4",
"commit_hash": "fc12656a1a62e5d69430bba6e4feb8cfbaf21542",
"identity_pubkey": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"alias": "StandUp",
"color": "#3399ff",
"num_pending_channels": 0,
"num_active_channels": 0,
"num_inactive_channels": 0,
"num_peers": 2,
"block_height": 1862848,
"block_hash": "000000000000000ecb6fd95e1f486283d48683aa3111b6c23144a2056f5a1532",
"best_header_timestamp": "1602632294",
"synced_to_chain": true,
"synced_to_graph": false,
"testnet": true,
"chains": [
{
"chain": "bitcoin",
"network": "testnet"
}
],
"uris": [
],
"features": {
"0": {
"name": "data-loss-protect",
"is_required": true,
"is_known": true
},
"5": {
"name": "upfront-shutdown-script",
"is_required": false,
"is_known": true
},
"7": {
"name": "gossip-queries",
"is_required": false,
"is_known": true
},
"9": {
"name": "tlv-onion",
"is_required": false,
"is_known": true
},
"13": {
"name": "static-remote-key",
"is_required": false,
"is_known": true
},
"15": {
"name": "payment-addr",
"is_required": false,
"is_known": true
},
"17": {
"name": "multi-path-payments",
"is_required": false,
"is_known": true
}
}
}
```
O ID deste node é `032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543`. Embora este comando não nos mostre o endereço IP e a porta, eles devem ser o endereço IP da nossa máquina e a porta `9735`.
## Escute a Fofoca
Se já estivéssemos conectados à Lightning Network, e nosso node já estivesse "fofocando" com seus pares, também poderíamos ser capazes de encontrar informações sobre os pares automaticamente, por meio do comando `listpeers`:
```
c$ lightning-cli --network=testnet listpeers
{
"peers": [
{
"id": "0302d48972ba7eef8b40696102ad114090fd4c146e381f18c7932a2a1d73566f84",
"connected": true,
"netaddr": [
"127.0.0.1:9736"
],
"features": "02a2a1",
"channels": []
}
]
}
```
No entanto, este definitivamente não será o caso na nossa primeira interação com a Lightning Network.
## Resumo: Prefácio: Acessando um Segundo Node Lightning
Sempre precisaremos de dois nodes Lightning para formar um canal. Se não tivermos outra pessoa que está testando as coisas conosco, precisaremos criar um segundo node, usanda c-lightning ou (como faremos em nossos exemplos) usando a LND.
## O Que Vem Depois?
Embora possivelmente tenhamos criado um LND, a c-lightning permanecerá no centro dos nossos exemplos até que precisemos começar a usar os dois, no [Capítulo 20](20_0_Using_Lightning.md).
Vamos continuar "Compreendendo Nossa Configuração da Lightning" na seção [§19.3: Criando um Canal Lightning](19_3_Setting_Up_a_Channel.md).

View File

@ -0,0 +1,185 @@
# 19.3: Criando um Canal Lightning
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Agora que entendemos o básico da configuração da Lightning e, com sorte, já criamos ou recebemos informações sobre um segundo node Lightning, estamos prontos para criar nosso primeiro canal na Lightning Network. Claro, precisaremos entender o que ele é e como é criado usando a c-lightning.
> :book: ***O que é um canal Lightning?*** De maneira simples, um canal Lightning é um tubo de dinheiro que permite transferências rápidas, baratas e privadas sem enviar transações para a blockchain. Mais tecnicamente, um canal é uma transação multisig 2-de-2 no Bitcoin que estabelece um relacionamento financeiro sem confiança entre duas pessoas ou dois agentes. Uma certa quantia de dinheiro é depositada no canal, quando então se mantém um banco de dados local com saldo em bitcoins para ambas as partes, mantendo o registro de qual é o saldo de cada parte. Os dois usuários podem então trocar bitcoins por meio do canal Lightning sem nunca escrever na blockchain do Bitcoin. Somente quando desejam fechar o canal é que eles dividem os bitcoins na blockchain, com base na divisão final das moedas para cada um.
> :book: ***Como os canais Lightning criam uma rede Lightning?*** Embora um canal Lightning só permita o pagamento entre dois usuários, os canais podem ser conectados para formar uma rede que permite pagamentos entre membros que não têm um canal direto entre eles. Isso cria uma rede entre várias pessoas, construída a partir de conexões em pares.
Nesta seção, continuaremos usando nossa configuraçãa c-lightning como nosso node principal.
## Criando um Canal
A criação de um canal Lightning requer as seguintes etapas:
* Financiar nossa carteira c-lightning com alguns satoshis;
* Conectar-se a um node remoto como um par;
* Abrir um canal.
### Financiando Nossa Carteira c-lightning
Para mover fundos para um canal Lightning, primeiro é necessário financiar nossa carteira c-lightning.
> :book: ***O que é uma carteira c-lightning?*** A implementação padrão da c-lightning vem com uma carteira Bitcoin integrada que permite enviar e receber transações de bitcoin na blockchain. Esta carteira será usada para criar novos canais.
A primeira coisa que precisamos fazer é enviar alguns satoshis para nossa carteira c-lightning. Podemos criar um novo endereço usando o comando `lightning-cli newaddr`. Isto gera um novo endereço que pode ser subsequentemente usado para financiar canais gerenciados pelo node c-lightning. Podemos especificar o tipo de endereço desejado; se não for especificado, o endereço gerado será um bech32.
```
$ lightning-cli --testnet newaddr
{
"address": "tb1qefule33u7ukfuzkmxpz02kwejl8j8dt5jpgtu6",
"bech32": "tb1qefule33u7ukfuzkmxpz02kwejl8j8dt5jpgtu6"
}
```
Podemos então enviar fundos para este endereço usando `bitcoin-cli sendtoaddress` (ou qualquer outro método de preferência). Para este exemplo, fizemos o envio que pode ser observado na transação [11094bb9ac29ce5af9f1e5a0e4aac2066ae132f25b72bff90fcddf64bf2feb02](https://mempool.space/pt/testnet/tx/11094bb9ac29ce5af9f1e5a0e4aac2066ae132f25b72bff90fcddf64bf2feb02).
Esta transação é chamada de [transação de financiamento](https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#funding-transaction-output) e precisa ser confirmada antes que os fundos possam ser utilizados.
> :book: ***O que é uma transação de financiamento?*** Uma transação de financiamento é uma transação de bitcoin que coloca dinheiro em um canal Lightning. Pode ser de financiamento único (por um participante) ou de financiamento duplo (por ambos). A partir daí, as transações da Lightning tratam de realocar a propriedade da transação de financiamento, mas só se ajustam na blockchain quando o canal é fechado.
Para verificar nosso saldo local, devemos usar o comando `lightning-cli listfunds`:
```
c$ lightning-cli --testnet listfunds
{
"outputs": [],
"channels": []
}
```
Como os fundos ainda não têm seis confirmações, não há saldo disponível. Após seis confirmações, devemos ver o saldo alterado:
```
c$ lightning-cli --testnet listfunds
{
"outputs": [
{
"txid": "11094bb9ac29ce5af9f1e5a0e4aac2066ae132f25b72bff90fcddf64bf2feb02",
"output": 0,
"value": 300000,
"amount_msat": "300000000msat",
"scriptpubkey": "0014ca79fcc63cf72c9e0adb3044f559d997cf23b574",
"address": "tb1qefule33u7ukfuzkmxpz02kwejl8j8dt5jpgtu6",
"status": "confirmed",
"blockheight": 1780680,
"reserved": false
}
],
"channels": []
}
```
Observe que o valor está listado em satoshis ou microsatoshis, não em Bitcoin!
> :book: ***O que são satoshis e msats?*** Já conhecemos os satoshis na seção [§3.4](03_4_Receiving_a_Transaction.md). Um satoshi é o centésimo milionésimo de um bitcoin, então 300.000 satoshis equivalem a 0,003 BTC. Um satoshi é a menor unidade monetária na rede Bitcoin. Mas, a rede Lightning pode ser menor, então 1.000 msat, ou milisatoshis, equivalem a um satoshi. Isso significa que 1 msat é o centésimo bilionésimo de um bitcoin e 300.000.000 msat equivalem a 0,003 BTC.
Agora que financiamos nossa carteira c-lightning, precisaremos de informações sobre um node remoto para começar a criar o processo do canal.
### Conectando a um Node Remoto
A próxima coisa que precisaremos fazer é conectar nosso node a um par. Isso é feito com o comando `lightning-cli connect`. Lembre-se que se quisermos mais informações sobre este comando, devemos digitar `lightning-cli help connect`.
Para conectar nosso node a um par remoto, precisaremos do nosso id, que representa a chave pública do node de destino. Por conveniência, o `ID` pode ter a forma `id@host` ou `id@host:port`. Podemos já ter pego esta informação com o `lightning-cli getinfo` (na c-lightning) ou `lncli --network=testnet getinfo` (no LND) conforme discutido no [adendo anterior](19_2__Interlude_Accessing_a_Second_Lightning_Node.md).
Selecionamos o node LND, `032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543`, que está localizado no endereço IP `45.33.35.151`, ao qual vamos nos conectar a partir de nosso node c-lightning:
```
$ lightning-cli --network=testnet connect 032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543@45.33.35.151
{
"id": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"features": "02a2a1"
}
```
### Abrindo um Canal
O comando fundchannel do RPC abre um canal de pagamento com um par ao comprometer uma transação de financiamento para a blockchain. Devemos usar o comando `lightning-cli fundchannel` para fazer isso, com os seguintes parâmetros:
* **id** é o retorno do id do peer da conexão;
* **amount** é o valor em satoshis retirado da carteira interna para financiar o canal. O valor não pode ser inferior ao limite mínimo, atualmente definido como 546 satoshis, nem superior a 16.777.215 satoshis (a menos que grandes canais tenham sido negociados com o par).
* **feerate** é o feerate opcional usado para a transação de abertura e como feerate inicial para transações de confirmação e HTLC.
* **announce** é um sinalizador opcional que aciona o anúncio deste canal ou não. O padrão é verdadeiro. Se desejarmos criar um canal privado, precisamos definí-lo como falso.
* **minconf** especifica o número mínimo de confirmações que saídas usadas no processo de abertura do canal devem ter. O padrão é 1.
* **utxos** especifica os utxos a serem usados para financiar o canal, como uma matriz de “txid:vout”.
Agora podemos abrir o canal assim:
```
$ lightning-cli --testnet fundchannel 032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543 100000 urgent true 1
{
"tx": "0200000000010193dc3337837f091718f47b71f2eae8b745ec307231471f6a6aab953c3ea0e3b50100000000fdffffff02a0860100000000002200202e30365fe321a435e5f66962492163302f118c13e215ea8928de88cc46666c1d07860100000000001600142fe02e5be9283e8c5bcb93ae61421baf8cb64f9c024730440220668a7c253c9fd83fc1b45e4a52823fb6bc5fad30da36240d4604f0d6981a6f4502202aeb1da5fbbc8790791ef72b3378005fe98d485d22ffeb35e54a6fbc73178fb2012103b3efe051712e9fa6d90008186e96320491cfe1ef1922d74af5bc6d3307843327c76c1c00",
"txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"channel_id": "1d3cf2126ae36e12be3aee893b385ed6a2e19b1da7f4e579e3ef15ca234d6966",
"outnum": 0
}
```
Para confirmar o status do canal, vamos usar o comando `lightning-cli listfunds`:
```
c$ lightning-cli --testnet listfunds
{
"outputs": [
{
"txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"output": 1,
"value": 99847,
"amount_msat": "99847000msat",
"scriptpubkey": "00142fe02e5be9283e8c5bcb93ae61421baf8cb64f9c",
"address": "tb1q9lszuklf9qlgck7tjwhxzssm47xtvnuu4jslf8",
"status": "unconfirmed",
"reserved": false
},
{
"txid": "b5e3a03e3c95ab6a6a1f47317230ec45b7e8eaf2717bf41817097f833733dc93",
"output": 1,
"value": 200000,
"amount_msat": "200000000msat",
"scriptpubkey": "0014ed54b65eae3da99b23a48bf8827c9acd78079469",
"address": "tb1qa42tvh4w8k5ekgay30ugyly6e4uq09rfpqf9md",
"status": "confirmed",
"blockheight": 1862831,
"reserved": true
}
],
"channels": [
{
"peer_id": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"connected": true,
"state": "CHANNELD_AWAITING_LOCKIN",
"channel_sat": 100000,
"our_amount_msat": "100000000msat",
"channel_total_sat": 100000,
"amount_msat": "100000000msat",
"funding_txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"funding_output": 0
}
]
}
```
Embora este novo canal com 100.000 satoshis não esteja confirmado, nosso estado será `CHANNELD_AWAITING_LOCKIN`. Observe que a alteração não confirmada de `99847` satoshis também está aparecendo como uma nova transação na carteira. Depois que todas as seis confirmações forem concluídas, o canal mudará para o estado `CHANNELD_NORMAL`, que será o estado permanente. Nesse momento, um `short_channel_id` também aparecerá, por exemplo:
```
"short_channel_id": "1862856x29x0",
```
Esses valores indicam onde a transação de financiamento pode ser encontrada na blockchain. Ela aparece na forma `bloco x txid x vout`.
Neste caso, `1862856x29x0` significa:
* Criado no bloco 1862856;
* Com um `txid` de 29 e;
* Um `vout` de 0.
Podemos precisar usar este `short_channel_id` para certos comandos na Lightning.
Esta transação de financiamento também pode ser encontrada onchain pelo TXID [66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d] (https://mempool.space/pt/testnet/tx/66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d)
> :book: ***O que é a capacidade do canal?*** Em um canal Lightning, ambos os lados do canal possuem uma parte da capacidade. O valor do seu lado do canal é chamado de *saldo local (local balance)* e o valor do outro lado é chamado de *saldo remoto (remote balance)*. Ambos os saldos podem ser atualizados muitas vezes sem fechar o canal (quando o saldo final é enviado para a blockchain), mas a capacidade do canal não pode mudar sem fechá-lo. A capacidade total de um canal é a soma do saldo de cada participante do canal.
## Resumo: Criando um Canal Lightning
Precisaremos criar um canal com um node remoto para poder receber e enviar dinheiro pela Lightning Network.
## O Que Vem Depois?
Você está pronto para passar para o [Capítulo 20: Usando a Lightning](20_0_Using_Lightning.md).

View File

@ -0,0 +1,25 @@
# Capítulo 20: Usando a Lightning
> :information_source: **NOTA:** Este é um rascunho que está em andamento, para que possa obter alguns comentários dos revisores iniciais. Ainda não está pronto.
Neste capítulo, continuaremos trabalhando com a interface de linha de comando `lightning-cli`. Criaremos invoices, realizaremos pagamentos e fecharemos canais, todas as principais atividades para se usar a Lightning.
## Objetivos Deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Efetuar pagamentos na Lightning Network;
* Aplicar o fechamento de um canal Lightning.
Os objetivos secundários do capítulo incluem a capacidade de:
* Compreender o formato dos invoices;
* Entender o ciclo de vida dos pagamentos da Lightning Network;
* Saber como expandir a Lightning Network.
## Tabela de Conteúdo
* [Seção 1: Gerando um Invoice](20_1_Generate_a_Payment_Request.md)
* [Seção 2: Pagando um Invoice](20_2_Paying_a_Invoice.md)
* [Seção 3: Fechando um Canal Lightning](20_3_Closing_a_Channel.md)
* [Seção 4: Expandindo a Lightning Network](20_4_Lightning_Network_Review.md)

View File

@ -0,0 +1,184 @@
# 20.1: Gerando um Invoice
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Esta seção descreve como os pagamentos funcionam na Lightning Network, como criar uma solicitação de pagamento (ou _invoice_) e, finalmente, como entendê-la. A emissão de invoices depende de termos um segundo node Lightning, conforme descrito na seção [Acessando um Segundo Node Lightning](19_2__Interlude_Accessing_a_Second_Lightning_Node.md). Esses exemplos usarão um node LND como nosso node secundário, para demonstrar ainda mais as possibilidades da Lightning Network. Para diferenciar entre os nodes nestes exemplos, os prompts serão mostrados como `c $` para o node c-lightning e `lnd $` para o node LND. Se quisermos reproduzir essas etapas, devemos [instalar nosso próprio node LND secundário](19_2__Interlude_Accessing_a_Second_Lightning_Node.md#Creating-a-new-lnd-node).
> :book: ***O que é um invoice?*** Quase todos os pagamentos feitos na Lightning Network exigem um invoice, que nada mais é do que um **pedido de pagamento** feito pelo destinatário do dinheiro e enviado por qualquer meio para o usuário que irá pagar. Todos os invoices são de uso único. Os invoices da Lightning usam a codificação bech32, que já é usada pela Segregated Witness para Bitcoin.
## Criando um Invoice
Para criar um novo invoice na c-lightning, usaríamos o comando `lightning-cli --testnet invoice`.
Vamos ver como funcionaria com o c-lightning, usando argumentos de um valor (em milisats), um rótulo e uma descrição.
```
c$ lightning-cli --testnet invoice 100000 joe-payment "The money you owe me for dinner"
{
"payment_hash": "07a1c4bd7a38b4dea35f301c173cd8f9aac253b66bd8404d7ad829f226342490",
"expires_at": 1603305795,
"bolt11": "lntb1u1p0cw3krpp5q7suf0t68z6dag6lxqwpw0xclx4vy5akd0vyqnt6mq5lyf35yjgqdpj235x2grddahx27fq09hh2gr0wajjqmt9ypnx7u3qv35kumn9wgxqyjw5qcqp2sp5r3puay46tffdyzldjv39fw6tzdgu2hnlszamqhnmgjsuxqxavpgs9qy9qsqatawvx44x5qa22m7td84jau5450v7j6sl5224tlv9k5v7wdygq9qr4drz795lfnl52gklvyvnha5e5lx72lzzmgzcfnp942va5thmhsp5sx7c2",
"warning_capacity": "No channels",
"warning_mpp_capacity": "The total incoming capacity is still insufficient even if the payer had MPP capability."
}
```
No entanto, para este exemplo, vamos gerar um invoice em um node LND e, em seguida, pagá-lo no node c-lightning. Isso requer o comando `addinvoice` ligeiramente diferente na LND. Podemos usar o argumento `--amt` para indicar a quantia a ser paga (em milisats) e adicionar uma descrição usando o argumento `--memo`.
```
lnd$ lncli -n testnet addinvoice --amt 10000 --memo "First LN Payment - Learning Bitcoin and Lightning from the Command line."
{
"r_hash": "6cacdedc95b89eec15e5244bd0957b88c0ab58b153eee549735b995344bc16bb",
"payment_request": "lntb100u1p0cwnqtpp5djkdahy4hz0wc909y39ap9tm3rq2kk9320hw2jtntwv4x39uz6asdr5ge5hyum5ypxyugzsv9uk6etwwssz6gzvv4shymnfdenjqsnfw33k76twypskuepqf35kw6r5de5kueeqveex7mfqw35x2gzrdakk6ctwvssxc6twv5hqcqzpgsp5a9ryqw7t23myn9psd36ra5alzvp6lzhxua58609teslwqmdljpxs9qy9qsq9ee7h500jazef6c306psr0ncru469zgyr2m2h32c6ser28vrvh5j4q23c073xsvmjwgv9wtk2q7j6pj09fn53v2vkrdkgsjv7njh9aqqtjn3vd",
"add_index": "1"
}
```
Observe que esses invoices não fazem referência direta ao canal que criamos: isso é necessário para o pagamento, mas não para solicitar o pagamento.
## Compreendendo um Invoice
O `bolt11 payment_request` que criamos é composto de duas partes: uma é legível por humanos e a outra são apenas dados.
> :book: **O que é um BOLT?** Os BOLTs são as [especificações individuais da Lightning Network](https://github.com/lightningnetwork/lightning-rfc).
### Lendo a Parte Legível do Invoice
A parte legível dos invoices começa com um `ln`. É `lnbc` para Bitcoin mainnet, `lntb` para Bitcoin testnet ou `lnbcrt` para Bitcoin regtest.
Em seguida, listamos os fundos solicitados no invoice.
Por exemplo, vamos olhar para a nossa fatura do node LND:
```
lntb100u1p0cwnqtpp5djkdahy4hz0wc909y39ap9tm3rq2kk9320hw2jtntwv4x39uz6asdr5ge5hyum5ypxyugzsv9uk6etwwssz6gzvv4shymnfdenjqsnfw33k76twypskuepqf35kw6r5de5kueeqveex7mfqw35x2gzrdakk6ctwvssxc6twv5hqcqzpgsp5a9ryqw7t23myn9psd36ra5alzvp6lzhxua58609teslwqmdljpxs9qy9qsq9ee7h500jazef6c306psr0ncru469zgyr2m2h32c6ser28vrvh5j4q23c073xsvmjwgv9wtk2q7j6pj09fn53v2vkrdkgsjv7njh9aqqtjn3vd
```
A parte legível por humanos é `ln` +`tb` + `100u`.
O `lntb` diz que esta é um invoice da Lightning Network para bitcoins Testnet.
O `100u` diz que é para 100 bitcoins vezes o multiplicador microsatoshi. Existem quatro multiplicadores de fundos (opcionais):
* `m` (mili): multiplique por 0,001
* `u` (micro): multiplique por 0,000001
* `n` (nano): multiplique por 0,000000001
* `p` (pico): multiplique por 0,000000000001
100 BTC * 0,000001 = 0,0001 BTC, que é o mesmo que 10.000 satoshis.
### Lendo a Parte do Invoice Referente aos Dados
O resto do invoice (`1p0cwnqtpp5djkdahy4hz0wc909y39ap9tm3rq2kk9320hw2jtntwv4x39uz6asdr5ge5hyum5ypxyugzsv9uk6etwwssz6gzvv4shymnfdenjqsnfw33k76twypskuepqf35kw6r5de5kueeqveex7mfqw35x2gzrdakk6ctwvssxc6twv5hqcqzpgsp5a9ryqw7t23myn9psd36ra5alzvp6lzhxua58609teslwqmdljpxs9qy9qsq9ee7h500jazef6c306psr0ncru469zgyr2m2h32c6ser28vrvh5j4q23c073xsvmjwgv9wtk2q7j6pj09fn53v2vkrdkgsjv7njh9aqqtjn3vd`) contém um marcador de tempo, dados especificamente marcados e uma assinatura. Obviamente, não pode ler sem decodificá-lo, mas podemos pedir ao `lightning-cli` para fazer isso com o comando `decodepay`:
```
c$ lightning-cli --testnet decodepay lntb100u1p0cwnqtpp5djkdahy4hz0wc909y39ap9tm3rq2kk9320hw2jtntwv4x39uz6asdr5ge5hyum5ypxyugzsv9uk6etwwssz6gzvv4shymnfdenjqsnfw33k76twypskuepqf35kw6r5de5kueeqveex7mfqw35x2gzrdakk6ctwvssxc6twv5hqcqzpgsp5a9ryqw7t23myn9psd36ra5alzvp6lzhxua58609teslwqmdljpxs9qy9qsq9ee7h500jazef6c306psr0ncru469zgyr2m2h32c6ser28vrvh5j4q23c073xsvmjwgv9wtk2q7j6pj09fn53v2vkrdkgsjv7njh9aqqtjn3vd
{
"currency": "tb",
"created_at": 1602702347,
"expiry": 3600,
"payee": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"msatoshi": 10000000,
"amount_msat": "10000000msat",
"description": "First LN Payment - Learning Bitcoin and Lightning from the Command line.",
"min_final_cltv_expiry": 40,
"payment_secret": "e946403bcb54764994306c743ed3bf1303af8ae6e7687d3cabcc3ee06dbf904d",
"features": "028200",
"payment_hash": "6cacdedc95b89eec15e5244bd0957b88c0ab58b153eee549735b995344bc16bb",
"signature": "304402202e73ebd1ef974594eb117e8301be781f2ba289041ab6abc558d432351d8365e902202a8151c3fd13419b9390c2b976503d2d064f2a6748b14cb0db64424cf4e572f4"
}
```
Aqui temos o que os elementos mais relevantes significam:
1. `currency`: A moeda a ser paga;
2. `created_at`: O momento em que a fatura foi criada. O valor é dado em tempo UNIX, que é segundos desde 1970.
3. `expiry`: O momento em que nosso node marca a fatura como inválida. O padrão é 1 hora ou 3600 segundos.
4. `payee`: A chave pública da pessoa (node) que recebe o pagamento da Lightning Network;
5. `msatoshi` e `amount_msat`: O valor de satoshis a ser pago;
6. `description`: A descrição informada pelo usuário;
7. `payment_hash`: O hash da pré-imagem que é usado para bloquear o pagamento. Só podemos resgatar um pagamento bloqueado com a pré-imagem correspondente ao hash de pagamento. Isso permite o roteamento na Lightning Network sem confiar em terceiros, criando um **Pagamento Condicional** a ser preenchido;
8. `signature`: A assinatura codificada por DER.
> :book: ***O que são pagamentos condicionais?*** Embora os canais Lightning sejam criados entre dois participantes, vários canais podem ser conectados juntos, formando uma rede de pagamento que permite envio de valores entre todos os participantes da rede, mesmo aqueles sem um canal direto entre eles. Isso é feito usando um contrato inteligente denominado **Hashed Time Locked Contract**.
> :book: ***O que é um Hashed Time Locked Contract (HTLC)?*** Um HTLC é um pagamento condicional que usa hashlocks e timelocks para garantir a segurança do pagamento. O destinatário deve apresentar uma pré-imagem do pagamento ou gerar um comprovante criptográfico de pagamento antes de um determinado prazo, caso contrário o pagador pode cancelar o contrato gastando-o. Esses contratos são criados como saídas da **Transação de Compromisso**.
> :book: ***O que é uma transação de compromisso?*** Uma transação de compromisso é uma transação que gasta a transação de financiamento original. Cada par possui a assinatura do outro par, o que significa que qualquer um pode gastar sua transação do compromisso como quiser. Depois que cada nova transação de confirmação é criada, a antiga é revogada. A transação de confirmação é uma maneira pela qual a transação de financiamento pode ser desbloqueada na blockchain, conforme discutiremos na seção [§20.3](20_3_Closing_a_Channel.md).
### Verificando Nosso Invoice
Existem dois elementos cruciais para verificar o invoice. O primeiro, obviamente, é o valor do pagamento, que já examinamos na parte legível. O segundo é o dado do `payee`, que é o pubkey do destinatário (node):
```
"payee": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
```
Precisamos verificar se ele é o destinatário esperado.
Olhando nas seções anteriores, mais precisamente na seção [§19.3](19_3_Setting_Up_a_Channel.md#opening-a-channel), podemos observar que é de fato o ID do par que usamos quando criamos nosso canal. Também podemos verificá-lo no outro node com o comando `getinfo`.
```
lnd$ lncli -n testnet getinfo
{
"version": "0.11.0-beta.rc4 commit=v0.11.0-beta.rc4",
"commit_hash": "fc12656a1a62e5d69430bba6e4feb8cfbaf21542",
"identity_pubkey": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"alias": "StandUp",
"color": "#3399ff",
"num_pending_channels": 0,
"num_active_channels": 1,
"num_inactive_channels": 0,
"num_peers": 3,
"block_height": 1862983,
"block_hash": "00000000000000c8c2f58f6da2ae2a3884d6e84f55d0e1f585a366f9dfcaa860",
"best_header_timestamp": "1602702331",
"synced_to_chain": true,
"synced_to_graph": true,
"testnet": true,
"chains": [
{
"chain": "bitcoin",
"network": "testnet"
}
],
"uris": [
],
"features": {
"0": {
"name": "data-loss-protect",
"is_required": true,
"is_known": true
},
"5": {
"name": "upfront-shutdown-script",
"is_required": false,
"is_known": true
},
"7": {
"name": "gossip-queries",
"is_required": false,
"is_known": true
},
"9": {
"name": "tlv-onion",
"is_required": false,
"is_known": true
},
"13": {
"name": "static-remote-key",
"is_required": false,
"is_known": true
},
"15": {
"name": "payment-addr",
"is_required": false,
"is_known": true
},
"17": {
"name": "multi-path-payments",
"is_required": false,
"is_known": true
}
}
}
```
No entanto, o `payee` também pode ser alguém novo, caso no qual provavelmente precisaremos verificar com a pessoa que emitiu o invoice para garantir que tudo está correto.
## Resumo: Gerando um Invoice
Na maioria dos casos, precisamos receber um invoice para usar os pagamentos da Lightning Network. Neste exemplo, criamos um manualmente, mas se estivermos em um ambiente de produção, provavelmente teriam sistemas fazendo isso automaticamente sempre que alguém adquirir produtos ou serviços. Claro, depois de receber um invoice, precisamos saber como lê-lo!
## O Que Vem Depois?
Vamos continuar "Usando a Lightning" na seção [§20.2: Pagando um Invoice](20_2_Paying_a_Invoice.md).

206
pt/20_2_Paying_a_Invoice.md Normal file
View File

@ -0,0 +1,206 @@
# 20.2: Pagando um Invoice
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Neste capítulo, aprenderemos como pagar um invoice usando o comando `lightning-cli pay`. Presume-se que já sabemos como analisar um invoice, de acordo com a seção [§20.1](20_1_Generate_a_Payment_Request.md), e se ele é válido.
## Verificando o Saldo
Obviamente, a primeira coisa que precisamos fazer é nos certificarmos de que possuímos fundos suficientes para pagar o invoice. Neste caso, o canal configurado anteriormente com `032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543` contém 100.000 satoshis. Este será o canal de pagamento do invoice.
```
c$ lightning-cli --testnet listfunds
{
"outputs": [
{
"txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"output": 1,
"value": 99847,
"amount_msat": "99847000msat",
"scriptpubkey": "00142fe02e5be9283e8c5bcb93ae61421baf8cb64f9c",
"address": "tb1q9lszuklf9qlgck7tjwhxzssm47xtvnuu4jslf8",
"status": "confirmed",
"blockheight": 1862856,
"reserved": false
}
],
"channels": [
{
"peer_id": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"connected": true,
"state": "CHANNELD_NORMAL",
"short_channel_id": "1862856x29x0",
"channel_sat": 100000,
"our_amount_msat": "100000000msat",
"channel_total_sat": 100000,
"amount_msat": "100000000msat",
"funding_txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"funding_output": 0
}
]
}
```
Se não tivermos fundos suficientes, precisamos criar um novo canal.
## Pagando Nosso Invoice
Vamos usar o comando `lightning-cli pay` para pagar o invoice. Ele tentará encontrar uma rota para o destino fornecido, para posteriormente enviar os fundos solicitados. Isso é muito simples porque há um canal direto entre o pagador e o destinatário:
```
c$ lightning-cli --testnet pay lntb100u1p0cwnqtpp5djkdahy4hz0wc909y39ap9tm3rq2kk9320hw2jtntwv4x39uz6asdr5ge5hyum5ypxyugzsv9uk6etwwssz6gzvv4shymnfdenjqsnfw33k76twypskuepqf35kw6r5de5kueeqveex7mfqw35x2gzrdakk6ctwvssxc6twv5hqcqzpgsp5a9ryqw7t23myn9psd36ra5alzvp6lzhxua58609teslwqmdljpxs9qy9qsq9ee7h500jazef6c306psr0ncru469zgyr2m2h32c6ser28vrvh5j4q23c073xsvmjwgv9wtk2q7j6pj09fn53v2vkrdkgsjv7njh9aqqtjn3vd
{
"destination": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"payment_hash": "6cacdedc95b89eec15e5244bd0957b88c0ab58b153eee549735b995344bc16bb",
"created_at": 1602704828.948,
"parts": 1,
"msatoshi": 10000000,
"amount_msat": "10000000msat",
"msatoshi_sent": 10000000,
"amount_sent_msat": "10000000msat",
"payment_preimage": "1af4a9bb830e49b6bc8f0bef980630e189e3794ad1705f06ad1b9c71571dce0c",
"status": "complete"
}
```
Vamos observar que todos os valores estão em `msats`, não em `sats`!
### Pagando o Invoice pela Lightning
No entanto, _não_ precisamos ter um canal com um node para pagá-lo. Só precisamos ter uma rota razoável pela Lightning Network.
Imagine que recebemos esta minúscula solicitação de pagamento de 11.111 msat:
```
c$ lightning-cli --testnet decodepay lntb111110p1p0cw43ppp5u0ngjytlw6ywec3x784jale4xd7h058g9u4mthcaf9rl2f7g8zxsdp2t9hh2gr0wajjqmt9ypnx7u3qv35kumn9wgs8gmm0yyxqyjw5qcqp2sp5kj4xhrthmfgcgyl84zaqpl9vvdjwm5x368kr09fu5nym74setw4s9qy9qsq8hxjr73ee77vat0ay603e4w9aa8ag9sa2n55xznk5lsfrjffxxdj2k0wznvcfa98l4a57s80j7dhg0cc03vwqdwehkujlzxgm0xyynqqslwhvl
{
"currency": "tb",
"created_at": 1602704929,
"expiry": 604800,
"payee": "02f3d74746934494fa378235e5bc44cfdbb5b8779d839263fb7f9218be032f6f61",
"msatoshi": 11111,
"amount_msat": "11111msat",
"description": "You owe me for dinner too!",
"min_final_cltv_expiry": 10,
"payment_secret": "b4aa6b8d77da518413e7a8ba00fcac6364edd0d1d1ec37953ca4c9bf56195bab",
"features": "028200",
"payment_hash": "e3e689117f7688ece226f1eb2eff35337d77d0e82f2bb5df1d4947f527c8388d",
"signature": "304402203dcd21fa39cfbcceadfd269f1cd5c5ef4fd4161d54e9430a76a7e091c929319b02202559ee14d984f4a7fd7b4f40ef979b743f187c58e035d9bdb92f88c8dbcc424c"
}
```
Se tentássemos pagar e não tivéssemos uma rota para o destinatário por meio da Lightning Network, poderíamos esperar um erro como este:
```
c$ lightning-cli --testnet pay lntb111110p1p0cw43ppp5u0ngjytlw6ywec3x784jale4xd7h058g9u4mthcaf9rl2f7g8zxsdp2t9hh2gr0wajjqmt9ypnx7u3qv35kumn9wgs8gmm0yyxqyjw5qcqp2sp5kj4xhrthmfgcgyl84zaqpl9vvdjwm5x368kr09fu5nym74setw4s9qy9qsq8hxjr73ee77vat0ay603e4w9aa8ag9sa2n55xznk5lsfrjffxxdj2k0wznvcfa98l4a57s80j7dhg0cc03vwqdwehkujlzxgm0xyynqqslwhvl
{
"code": 210,
"message": "Ran out of routes to try after 11 attempts: see `paystatus`",
"attempts": [
{
"status": "failed",
"failreason": "Error computing a route to 02f3d74746934494fa378235e5bc44cfdbb5b8779d839263fb7f9218be032f6f61: \"Could not find a route\" (205)",
"partid": 1,
"amount": "11111msat"
},
...
```
Mas e se um host com o qual tínhamos um canal aberto é o destinatário pretendido?
Nesse caso, quando formos pagar a fatura, ele _automaticamente funcionará_!
```
c$ lightning-cli --testnet pay lntb111110p1p0cw43ppp5u0ngjytlw6ywec3x784jale4xd7h058g9u4mthcaf9rl2f7g8zxsdp2t9hh2gr0wajjqmt9ypnx7u3qv35kumn9wgs8gmm0yyxqyjw5qcqp2sp5kj4xhrthmfgcgyl84zaqpl9vvdjwm5x368kr09fu5nym74setw4s9qy9qsq8hxjr73ee77vat0ay603e4w9aa8ag9sa2n55xznk5lsfrjffxxdj2k0wznvcfa98l4a57s80j7dhg0cc03vwqdwehkujlzxgm0xyynqqslwhvl
{
"destination": "02f3d74746934494fa378235e5bc44cfdbb5b8779d839263fb7f9218be032f6f61",
"payment_hash": "e3e689117f7688ece226f1eb2eff35337d77d0e82f2bb5df1d4947f527c8388d",
"created_at": 1602709081.324,
"parts": 1,
"msatoshi": 11111,
"amount_msat": "11111msat",
"msatoshi_sent": 12111,
"amount_sent_msat": "12111msat",
"payment_preimage": "ec7d1b28a7b877cd92b83be396899e8bfc3ecb0b4f944f65afb4be7d0ee72617",
"status": "complete"
}
```
Essa é a verdadeira beleza da Lightning Network: sem nenhum esforço dos participantes ponto a ponto, nossos canais individuais se tornam uma rede!
> :book: ***Como funcionam os pagamentos na rede?*** Digamos que o node A tem um canal aberto com o node B, o node B tem um canal aberto com o node C e o node A recebe uma fatura do node C de 11.111 msat. O node A paga ao node B 11.111 msat, mais uma pequena taxa, e então o node B paga 11.111 msat ao node C. Muito fácil. Mas lembre-se de que todos os canais são, na verdade, apenas registros de quem é o proprietário e de quanto é a Transação de Financiamento. Então o que realmente acontece é 11.111 msat da Transação de Financiamento no canal AB muda de A para B e, em seguida, 11.111 msat da Transação de Financiamento no canal BC muda de B para C. Isso significa que duas coisas são necessárias para que este pagamento funcione: primeiro, cada canal deve ter capacidade suficiente para o pagamento; e segundo, o pagador em cada canal deve possuir o suficiente da capacidade para fazer o pagamento.
Observe que, neste exemplo, 12.111 msat foram enviados para pagar uma fatura de 11.111 msat: o extra sendo uma taxa fixa muito pequena (não uma porcentagem) que foi paga ao intermediário.
## Verificando Nosso Saldo
Após efetuar um pagamento com sucesso, veremos que nossos fundos foram alterados corretamente.
Aqui está a aparência dos fundos para o node pagador após o pagamento inicial de 10.000 satoshis:
```
c$ lightning-cli --testnet listfunds
{
"outputs": [
{
"txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"output": 1,
"value": 99847,
"amount_msat": "99847000msat",
"scriptpubkey": "00142fe02e5be9283e8c5bcb93ae61421baf8cb64f9c",
"address": "tb1q9lszuklf9qlgck7tjwhxzssm47xtvnuu4jslf8",
"status": "confirmed",
"blockheight": 1862856,
"reserved": false
}
],
"channels": [
{
"peer_id": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"connected": true,
"state": "CHANNELD_NORMAL",
"short_channel_id": "1862856x29x0",
"channel_sat": 90000,
"our_amount_msat": "90000000msat",
"channel_total_sat": 100000,
"amount_msat": "100000000msat",
"funding_txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"funding_output": 0
}
]
}
```
Observe que a capacidade do canal permanece em 100.000 satoshis (isso nunca irá mudar!), mas que o `our_amount` agora é de apenas 90.000 satoshis (ou 90.000.000 msat).
Depois de pagar a segunda fatura, de 11.111 msat, os fundos mudam novamente:
```
$ lightning-cli --testnet listfunds
{
"outputs": [
{
"txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"output": 1,
"value": 99847,
"amount_msat": "99847000msat",
"scriptpubkey": "00142fe02e5be9283e8c5bcb93ae61421baf8cb64f9c",
"address": "tb1q9lszuklf9qlgck7tjwhxzssm47xtvnuu4jslf8",
"status": "confirmed",
"blockheight": 1862856,
"reserved": false
}
],
"channels": [
{
"peer_id": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"connected": true,
"state": "CHANNELD_NORMAL",
"short_channel_id": "1862856x29x0",
"channel_sat": 89987,
"our_amount_msat": "89987000msat",
"channel_total_sat": 100000,
"amount_msat": "100000000msat",
"funding_txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"funding_output": 0
}
]
}
```
O `our_amount` agora é de apenas 89.987 satoshis, tendo pago 11.111 msat mais uma taxa de 1.000 msat.
## Resumo: Pagando um Invoice
Depois de recebermos um invoice, é fácil pagar com um único comando na Lightning. Mesmo se não tivermos um canal para o destinatário, o pagamento é simples, desde que haja uma rota entre nós e o node de destino.
## O Que Vem Depois?
Vamos continuar "Usando a Lightning" na seção [§20.3: Fechando um Canal Lightning](20_3_Closing_a_Channel.md).

View File

@ -0,0 +1,259 @@
# 20.3: Fechando um Canal
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Neste capítulo, aprenderemos como fechar um canal usando a interface de linha de comando `lightning-cli close`. Fechar um canal significa que nós e a nossa contraparte enviarão o saldo do canal acordado para a blockchain, pelo qual devemos pagar as taxas de transação e esperar que a mesma seja posta em um bloco. Um fechamento pode ser cooperativo ou não, mas funciona de qualquer maneira.
Para fechar um canal, primeiro precisamos saber o ID do node remoto. Podemos recuperá-lo de duas maneiras.
## Encontrando Nossos Canais Pelos Saldos
Podemos usar o comando `lightning-cli listfunds` para ver nossos canais. Este comando RPC exibe todos os fundos disponíveis, em `outputs` não gastos (UTXOs) na carteira interna ou bloqueados em `channels` (canais) abertos.
```
c$ lightning-cli --testnet listfunds
{
"outputs": [
{
"txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"output": 1,
"value": 99847,
"amount_msat": "99847000msat",
"scriptpubkey": "00142fe02e5be9283e8c5bcb93ae61421baf8cb64f9c",
"address": "tb1q9lszuklf9qlgck7tjwhxzssm47xtvnuu4jslf8",
"status": "confirmed",
"blockheight": 1862856,
"reserved": false
}
],
"channels": [
{
"peer_id": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"connected": true,
"state": "CHANNELD_NORMAL",
"short_channel_id": "1862856x29x0",
"channel_sat": 89987,
"our_amount_msat": "89987000msat",
"channel_total_sat": 100000,
"amount_msat": "100000000msat",
"funding_txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"funding_output": 0
}
]
}
"message_flags": 1,
"channel_flags": 2,
"active": true,
"last_update": 1595508075,
"base_fee_millisatoshi": 1000,
"fee_per_millionth": 1,
"delay": 40,
"htlc_minimum_msat": "1000msat",
"htlc_maximum_msat": "280000000msat",
"features": ""
}
```
Poderíamos também recuperar o ID do enésimo canal em uma variável como esta:
```
c$ nodeidremote=$(lightning-cli --testnet listfunds | jq '.channels[0] | .peer_id')
```
## Encontrando Canais Usando o JQ
A outra maneira de encontrar canais para serem fechados é usando o comando `listchannels`. Ele retorna dados dos canais que são conhecidos pelo node. Como os canais podem ser bidirecionais, até dois nodes serão retornados por cada canal (um para cada direção).
No entanto, assim como no mundo real, a fofoca (gossip) da Lightning Network é muito eficaz e, em pouco tempo, iremos conhecer milhares de canais. Isso é ótimo para enviar pagamentos via Lightning Network, mas é pouco útil para descobrir os nossos próprios canais. Fazer isso requer um pouco de trabalho com `jq`.
Primeiro, precisamos saber nosso próprio ID do node, que pode ser recuperado com o `getinfo`:
```
c$ nodeid=$(lightning-cli --testnet getinfo | jq .id)
c$ echo $nodeid
"03240a4878a9a64aea6c3921a434e573845267b86e89ab19003b0c910a86d17687"
c$
```
Podemos então usar isso para procurar nos `listchannels` quaisquer canais onde nosso node seja a origem ou o destino:
```
c$ lightning-cli --testnet listchannels | jq '.channels[] | select(.source == '$nodeid' or .destination == '$nodeid')'
{
"source": "03240a4878a9a64aea6c3921a434e573845267b86e89ab19003b0c910a86d17687",
"destination": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"short_channel_id": "1862856x29x0",
"public": true,
"satoshis": 100000,
"amount_msat": "100000000msat",
"message_flags": 1,
"channel_flags": 0,
"active": true,
"last_update": 1602639570,
"base_fee_millisatoshi": 1,
"fee_per_millionth": 10,
"delay": 6,
"htlc_minimum_msat": "1msat",
"htlc_maximum_msat": "99000000msat",
"features": ""
}
```
Aqui está nosso node favorito `032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543` novamente, como sendo o destino.
Depois de saber o que temos, podemos armazená-lo em uma variável:
```
c$ nodeidremote=$(lightning-cli --testnet listchannels | jq '.channels[] | select(.source == '$nodeid' or .destination == '$nodeid') | .destination')
```
## Fechando um Canal
Agora que temos um ID do node remoto, estamos prontos para usar o comando `lightning-cli close` para fechar um canal. Por padrão, ele tentará fechar o canal cooperativamente com o par; se quisermos fechá-lo unilateralmente, precisamos definir o argumento `unilateraltimeout` com o número de segundos de espera. Se definirmos como sendo 0 e o par estiver online, um fechamento mútuo ainda irá ser tentado. Para este exemplo, tentaremos um fechamento mútuo.
```
c$ lightning-cli --testnet close $nodeidremote 0
{
"tx": "02000000011d3cf2126ae36e12be3aee893b385ed6a2e19b1da7f4e579e3ef15ca234d69660000000000ffffffff021c27000000000000160014d39feb57a663803da116402d6cb0ac050bf051d9cc5e01000000000016001451c88b44420940c52a384bd8a03888e3676c150900000000",
"txid": "f68de52d80a1076e36c677ef640539c50e3d03f77f9f9db4f13048519489593f",
"type": "mutual"
}
```
A transação de fechamento na blockchain é [f68de52d80a1076e36c677ef640539c50e3d03f77f9f9db4f13048519489593f] (https://blockstream.info/testnet/tx/f68de52d80a1076e36c67795f9f9db4f13048519489593f].
É essa transação de fechamento que realmente gasta os fundos que foram negociados de um lado para outro por meio de transações Lightning. Isso pode ser visto examinando a transação:
```
$ bitcoin-cli --named getrawtransaction txid=f68de52d80a1076e36c677ef640539c50e3d03f77f9f9db4f13048519489593f verbose=1
{
"txid": "f68de52d80a1076e36c677ef640539c50e3d03f77f9f9db4f13048519489593f",
"hash": "3a6b3994932ae781bab80e159314bad06fc55d3d33453a1d663f9f9415c9719c",
"version": 2,
"size": 334,
"vsize": 169,
"weight": 673,
"locktime": 0,
"vin": [
{
"txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"txinwitness": [
"",
"304402207f8048e29192ec86019bc83be8b4cac5d1fc682374538bed0707f58192d41c390220512ebcde122d53747feedd70c09153a40c56d09a5fec02e47642afdbb20aa2ac01",
"3045022100d686a16084b60800fa0f6b14c25dca1c13d10a55c5fb7c6a3eb1c5f4a2fb20360220555f5b6e672cf9ef82941f7d46ee03dd52e0e848b9f094a41ff299deb8207cab01",
"522102f7589fd8366252cdbb37827dff65e3304abd5d17bbab57460eff71a9e32bc00b210343b980dff4f2723e0db99ac72d0841aad934b51cbe556ce3a1b257b34059a17052ae"
],
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00010012,
"n": 0,
"scriptPubKey": {
"asm": "0 d39feb57a663803da116402d6cb0ac050bf051d9",
"hex": "0014d39feb57a663803da116402d6cb0ac050bf051d9",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1q6w07k4axvwqrmggkgqkkev9vq59lq5we5fcrzn"
]
}
},
{
"value": 0.00089804,
"n": 1,
"scriptPubKey": {
"asm": "0 51c88b44420940c52a384bd8a03888e3676c1509",
"hex": "001451c88b44420940c52a384bd8a03888e3676c1509",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1q28ygk3zzp9qv223cf0v2qwygudnkc9gfp30ud4"
]
}
}
],
"hex": "020000000001011d3cf2126ae36e12be3aee893b385ed6a2e19b1da7f4e579e3ef15ca234d69660000000000ffffffff021c27000000000000160014d39feb57a663803da116402d6cb0ac050bf051d9cc5e01000000000016001451c88b44420940c52a384bd8a03888e3676c1509040047304402207f8048e29192ec86019bc83be8b4cac5d1fc682374538bed0707f58192d41c390220512ebcde122d53747feedd70c09153a40c56d09a5fec02e47642afdbb20aa2ac01483045022100d686a16084b60800fa0f6b14c25dca1c13d10a55c5fb7c6a3eb1c5f4a2fb20360220555f5b6e672cf9ef82941f7d46ee03dd52e0e848b9f094a41ff299deb8207cab0147522102f7589fd8366252cdbb37827dff65e3304abd5d17bbab57460eff71a9e32bc00b210343b980dff4f2723e0db99ac72d0841aad934b51cbe556ce3a1b257b34059a17052ae00000000",
"blockhash": "000000000000002a214b1ffc3a67c64deda838dd24d12154c15d3a6f1137e94d",
"confirmations": 1,
"time": 1602713519,
"blocktime": 1602713519
}
```
A entrada da transação é `66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d`, que foi a transação de financiamento feita na seção [§19.3](19_3_Setting_Up_a_Channel.md). A transação tem duas saídas, uma para o node remoto e outra para a carteira local da c-lightning. A saída no índice 0 corresponde ao node remoto com um valor de 0,00010012 BTC e, a saída no índice 1 corresponde ao node local com um valor de 0,00089804 BTC.
A Lightning mostrará da mesma forma 89.804 satoshis retornados como um novo UTXO em nossa carteira:
```
$ lightning-cli --network=testnet listfunds
{
"outputs": [
{
"txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"output": 1,
"value": 99847,
"amount_msat": "99847000msat",
"scriptpubkey": "00142fe02e5be9283e8c5bcb93ae61421baf8cb64f9c",
"address": "tb1q9lszuklf9qlgck7tjwhxzssm47xtvnuu4jslf8",
"status": "confirmed",
"blockheight": 1862856,
"reserved": false
},
{
"txid": "f68de52d80a1076e36c677ef640539c50e3d03f77f9f9db4f13048519489593f",
"output": 1,
"value": 89804,
"amount_msat": "89804000msat",
"scriptpubkey": "001451c88b44420940c52a384bd8a03888e3676c1509",
"address": "tb1q28ygk3zzp9qv223cf0v2qwygudnkc9gfp30ud4",
"status": "confirmed",
"blockheight": 1863006,
"reserved": false
}
],
"channels": [
{
"peer_id": "032a7572dc013b6382cde391d79f292ced27305aa4162ec3906279fc4334602543",
"connected": false,
"state": "ONCHAIN",
"short_channel_id": "1862856x29x0",
"channel_sat": 89987,
"our_amount_msat": "89987000msat",
"channel_total_sat": 100000,
"amount_msat": "100000000msat",
"funding_txid": "66694d23ca15efe379e5f4a71d9be1a2d65e383b89ee3abe126ee36a12f23c1d",
"funding_output": 0
}
]
}
```
### Compreendendo os Tipos de Canais de Fechamento.
O comando `close` do RPC tenta fechar um canal cooperativamente com nosso par ou unilateralmente após o argumento `unilateraltimeout` expirar. Isso traz alguma discussão adicional, pois vai ao cerne do design que não precisa de nenhuma confiança da Lightning:
Cada participante de um canal pode criar tantos pagamentos Lightning para a contraparte quanto os fundos permitirem. Na maioria das vezes não haverá desentendimentos entre os participantes, portanto, haverá apenas duas transações na rede, uma abrindo e outra fechando o canal. No entanto, pode haver cenários em que um par não está online ou não concorda com o estado final do canal ou quando alguém tenta roubar fundos da outra parte. É por isso que existem fechamentos cooperativos e forçados.
#### Fechamento Cooperativo
No caso de um fechamento cooperativo, ambos os participantes do canal concordam em fechar o canal e estabelecer o estado final na blockchain. Ambos os participantes devem estar online, pois o fechamento é realizado transmitindo um gasto incondicional da transação de financiamento com uma saída para cada par.
#### Fechamento Forçado
No caso de fechamento forçado, apenas um participante está online ou os participantes discordam sobre o estado final do canal. Nessa situação, um par pode realizar um fechamento unilateral do canal sem a cooperação do outro node. É executado transmitindo uma transação de confirmação que confirma o estado do canal anterior que ambas as partes concordaram. Esta transação de compromisso contém o estado do canal dividido em duas partes: o saldo de cada participante e todos os pagamentos pendentes (HTLCs).
Para realizar este tipo de fechamento, devemos especificar um argumento `unilateraltimeout`. Se este valor não for zero, o comando de fechamento fechará unilateralmente o canal quando esse número de segundos for atingido:
```
c$ lightning-cli --network=testnet close $newidremote 60
{
"tx": "0200000001a1091f727e6041cc93fead2ea46b8402133f53e6ab89ab106b49638c11f27cba00000000006a40aa8001df85010000000000160014d22818913daf3b4f86e0bcb302a5a812d1ef6b91c6772d20",
"txid": "02cc4c647eb3e06f37fcbde39871ebae4333b7581954ea86b27b85ced6a5c4f7",
"type": "unilateral"
}
```
## Resumo: Fechando um Canal
Ao fechar um canal, realizamos uma transação na blockchain encerrando nosso relacionamento financeiro com o node remoto. Para fechar um canal, devemos levar em consideração nosso status e o tipo de fechamento que desejamos executar.
## O Que Vem Depois?
Vamos continuar "Usando a Lightning" na seção [§20.4: Expandindo a Lightning Network](20_4_Lightning_Network_Review.md).

View File

@ -0,0 +1,60 @@
# 20.4: Expandindo a Lightning Network
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
Esses dois capítulos cobriram apenas algumas das atividades mais importantes da Lightning. Há muito mais que pode ser feito e muitas variedades possíveis. A seguir, daremos algumas dicas importantes.
## Usando Plugins c-lightning
O c-lightning é uma implementação leve, altamente personalizável e compatível com o padrão do protocolo Lightning Network. Ele estende a funcionalidade usando plugins. Principalmente, esses são subprocessos que são iniciados pelo daemon `lightningd` e podem interagir com o `lightningd` de várias maneiras:
* As opções de linha de comando permitem que os plugins registrem os próprios argumentos usando a linha de comando, que são então expostos por meio do `lightningd`;
* A passagem de comando JSON-RPC permite que os plugins adicionem os próprios comandos à interface JSON-RPC;
* As assinaturas de fluxo de eventos fornecem plug-ins com um mecanismo de notificação baseados em push para o `lightnind`;
* Hooks são uma opção primitiva que permite que os plugins sejam notificados sobre eventos no daemon `lightningd` e modifiquem o comportamento ou transmitam comportamentos personalizados.
Um plugin pode ser escrito em qualquer linguagem e pode se comunicar com o `lightningd` através do stdin e stdout do plugin. O JSON-RPCv2 é usado como protocolo no topo dos dois fluxos, com o plugin atuando como servidor e `lightningd` atuando como cliente.
O repositório `lightningd` GitHub mantém uma lista atualizada de [plugins](https://github.com/lightningd/plugins) disponíveis.
## Usando Carteiras Mobile
Atualmente, sabemos de duas carteiras de dispositivos móveis da Lightning que suportam a implementação do c-lightning.
Para dispositivos iOS, o FullyNoded é uma carteira de Bitcoin iOS open source que se conecta através do serviço autenticado Tor V3 ao nosso próprio full node. A funcionalidade FullyNoded está atualmente em desenvolvimento ativo e na fase beta inicial de testes.
* [FullyNoded](https://github.com/Fonta1n3/FullyNoded/blob/master/Docs/Lightning.md)
O SparkWallet é uma carteira GUI minimalista para a c-lightning, acessível pela web ou por meio de aplicativos móveis e de desktop para Android.
* [SparkWallet](https://github.com/shesek/spark-wallet)
## Usando Diferentes Implementações da Lightning
O c-lightning não é a nossa única opção. Hoje, existem três implementações amplamente utilizadas para a Lightning Network. Todos seguem as [Documentações Base para a Tecnologia Lightning (BOLT)](https://github.com/lightningnetwork/lightning-rfc), que descrevem um protocolo de segunda camada para transferências de bitcoins off-chain. As especificações são atualmente um trabalho em andamento que ainda está sendo elaborado.
| Nome | Descrição | BitcoinStandup | Linguagem | Repositório |
| ------------- | ------------- | :---: | ------------- | ------------- |
| C-lighting | Blockstream | X | C | [Download](https://github.com/ElementsProject/lightning) |
| LND | Lightning Labs | X | Go | [Download](https://github.com/lightningnetwork/lnd) |
| Eclair | ACINQ | - | Scala | [Download](https://github.com/ACINQ/eclair) |
## Fazendo Backups
Nosso node Lightning precisa estar online o tempo todo, caso contrário, nossa contraparte pode enviar um status de canal anterior e roubar nossos fundos. No entanto, há outro cenário em que os fundos podem ser perdidos, que é quando ocorre uma falha no hardware que impede o node de estabelecer um fechamento cooperativo com a contraparte. Isso provavelmente significará que, se não tivermos uma cópia exata do estado do canal antes da falha, teremos um estado inválido que pode fazer com que o outro node o considere como uma tentativa de fraude e use a transação penalizada. Nesse caso, todos os fundos serão perdidos. Para evitar esta situação indesejável, uma solução baseada na alta disponibilidade do banco de dados postgreSQL [existe](https://github.com/gabridome/docs/blob/master/c-lightning_with_postgresql_reliability.md).
PS: Não testamos esta solução.
## Resumo: Expandindo a Lightning Network
Podemos usar diferentes implementações, plugins, carteiras para celular e backups para expandir nossa experiência com a Lightning.
## O Que Vem Depois?
Concluímos todo o livro Aprendendo sobre o Bitcoin usando a Linha de Comando. Embora não precisemos visitar os [Apêndices](A0_Appendices.md), que possuem configurações alternativas, podemos fazer isso agora.
Caso contrário, nós o encorajamos a ingressar nas comunidades de desenvolvedores e programadores e também, colocar seu novo conhecimento para funcionar.
Você também pode nos ajudar aqui na Blockchain Commons com issues ou PRs para Aprendendo Bitcoin ou para qualquer um de nossos outros repositórios, ou pode até mesmo se tornar um [patrocinador](https://github.com/sponsors/BlockchainCommons). Também pode ajudar divulgando o trabalho, contando às pessoas nas redes sociais sobre o curso e o que aprendeu com ele!
Agora vá lá e faça da comunidade do Bitcoin um lugar melhor!

22
pt/A0_Appendices.md Normal file
View File

@ -0,0 +1,22 @@
# Apêndices
O foco principal deste curso sugere uma configuração bastante padrão para os testes de Bitcoin. À seguir, vamos ver alguns apêndices que irão explicar melhor dessa configuração e algumas opções alternativas.
## Objetivos desta Seção
Depois de trabalhar nestes apêndices, um desenvolvedor será capaz de:
* Decidir entre vários métodos de como criar uma blockchain do Bitcoin.
Os objetivos secundários do apêndice incluem a capacidade de:
* Compreender a configuração do Bitcoin Standup;
* Fazer uma compilação de Bitcoin à mão;
* Compreender o poder do Regtest;
* Use um ambiente Regtest.
## Tabela de Conteúdo
* [Apêndice 1: Compreendendo o Bitcoin Standup](A1_0_Understanding_Bitcoin_Standup.md)
* [Apêndice 2: Compilando Bitcoin da Fonte](A2_0_Compiling_Bitcoin_from_Source.md)
* [Apêndice 3: Usando o Regtest do Bitcoin](A3_0_Using_Bitcoin_Regtest.md)

View File

@ -0,0 +1,51 @@
# Apêndice 1: Compreendendo o Bitcoin Standup
Na seção [§2.1: Configurando um Bitcoin Core VPS com StackScript](02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md) explicamos o processo de criação de um node de Bitcoin usando [Bitcoin-Standup-Scripts](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts). O apêndice à seguir explica o que as principais seções do script fazem. Podemos acompanhar em [Linode Standup](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts/blob/master/Scripts/LinodeStandUp.sh) em outra janela.
## Etapa 1: Nome do Host
O nome do seu host é armazenado em `/etc/hostname` e definido com o comando `hostname`. Ele também aparece em `/etc/hosts`.
## Etapa 2: Fuso Horário
O fuso horário do nosso host é armazenado em `/etc/timezone`, então um arquivo apropriado do `/usr/share/zoneinfo/` é copiado para o `/etc/localtime`.
## Etapa 3: Atualizando o Debian
O gerenciador de pacotes `apt-get` é usado para deixar nossa máquina atualizada e instalar o `gnupg`, o gerador de números aleatórios `haveged`, e o firewall simples `ufw`.
Nossa máquina está configurada para se manter automaticamente atualizada com o `echo "unattended-upgrades unattended-upgrades / enable_auto_updates boolean true "| debconf-set-selections`.
## Etapa 4: Configurando um Usuário
Um usuário `standup` é criado, o qual será usado para nossas aplicações do Bitcoin. Ele também tem permissões `sudo`, permitindo que executemos ações privilegiadas com este usuário.
Se fornecemos uma chave SSH, ela permitirá o acesso a esta conta (caso contrário, devemos usar a senha criada na configuração).
Se fornecemos um endereço IP, o acesso `ssh` será limitado a esse endereço, de acordo com `/etc/hosts.allow`.
## Etapa 5: Configurando o Tor
O Tor é instalado para fornecer serviços protegidos (ocultos) para acessar os comandos RPC do Bitcoin através do nosso servidor. Podemos consultar a seção [§14.1: Verificando Nossa Configuração do Tor](14_1_Verifying_Your_Tor_Setup.md) para obter mais informações sobre a configuração do Tor.
Se criarmos um cliente autorizado para os serviços ocultos, o acesso será limitado a essa chave, que está em `/var/lib/tor/standup/authorized_clients`. Caso contrário, na seção [§14.2](14_2_Changing_Your_Bitcoin_Hidden_Services.md) explicamos como podemos fazê-la depois.
## Etapa 6: Instalando o Bitcoin
Bitcoin é instalado no `~standup/.bitcoin`. Nossa configuração é armazenada no `~standup/.bitcoin/bitcoin.conf`.
Precisamos nos certificar de que as somas de verificação (checksum) foram analisadas de acordo com a seção [§2.1](02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md), caso contrário, podemos estar expostos a um ataque de cadeia de produção.
## Etapa 7: Instalando o Codificador QR
Para manter tudo compatível com [GordianSystem](https://github.com/BlockchainCommons/GordianSystem), um código QR é criado e está em `/qrcode.png`. Isso pode ser lido em um cliente QuickConnect como [GordianWallet](https://github.com/BlockchainCommons/GordianWallet-iOS).
## Conclusão - Compreendendo o Bitcoin Standup
O Bitcoin Standup usa scripts para tentar combinar muitas das funcionalidades de um [GordianNode](https://github.com/BlockchainCommons/GordianNode-macOS). Ele deve fornecer a nós um ambiente Bitcoin seguro construído em uma base de Bitcoin Core com Tor para nos comunicarmos com o RPC.
## O Que Vem Depois?
Se estivermos no processo de criação de um node Bitcoin para o uso neste curso, devemos voltar para a seção [§2.1](02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md).
Se estivermos lendo os apêndices, podemos continuar no [Apêndice 2: Compilando Bitcoin da Fonte](A2_0_Compiling_Bitcoin_from_Source.md).

View File

@ -0,0 +1,127 @@
# Apêndice 2: Compilando Bitcoin da Fonte
Este curso presume o uso de um script para criar um ambiente Bitcoin, seja usando o Bitcoin Standup do Linode de acordo com o especificado na seção [§2.1](02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md), ou por algum outro meio de acordo com a seção [§2.2](02_2_Setting_Up_Bitcoin_Core_Other.md). No entanto, podemos querer compilar o Bitcoin manualmente.
Isso tem os seguintes benefícios:
1. Sempre estará atualizado com a versão mais recente. Mas atenção! Estar sempre atualizado não é necessário para o Bitcoin Core, pois o software é sempre compatível com versões anteriores, o que significa que uma versão antiga do Bitcoin Core ainda poderá participar da rede Bitcoin, embora possamos não ter os recursos mais recentes. Devemos sempre verificar os recursos de uma nova versão antes de atualizarmos.
2. Não precisaremos depender de binários do Bitcoin Core pré-compilados. Isso requer menos confiança. Mesmo que os mantenedores do Bitcoin Core façam um ótimo trabalho em manter a integridade do código, algumas etapas do código-fonte são removidas de um binário pré-compilado. Quando compilamos a partir do código-fonte, o código pode ser inspecionado antes da compilação.
3. Podemos personalizar a construção, fazendo coisas como desabilitar a carteira ou a GUI.
## Preparando Nosso Ambiente
Este tutorial usa o sistema operacional Debian 10.4.kv0 em uma arquitetura amd64 (computadores de 64 bits), mas podemos usar este tutorial em qualquer sistema baseado no Debian (por exemplo, Ubuntu, Mint, etc). Para outros sistemas Linux, podemos adaptar as etapas a seguir com o gerenciador de pacotes do sistema.
Podemos ter pouca ou nenhuma familiaridade com a linha de comando, desde que tenhamos vontade de aprender. O terminal é o nosso aliado mais poderoso, e não algo a ser temido. Podemos simplesmente copiar e colar os seguintes comandos para compilar o Bitcoin. Um comando com um "$" é um comando do usuário normal e um com um "#" é um comando de super usuário/root.
Se o nosso usuário não estiver na lista dos super usuários, podemos o seguinte:
```
$ su root
<escreva a senha root>
# apt-get install sudo
# usermod -aG sudo <nome do usuário>
# reboot
```
## Instalando o Bitcoin
### Etapa 1: Atualizando Nosso Sistema
Primeiro, vamos atualizar o sistema usando:
```
$ sudo apt-get update
```
### Etapa 2: Instalando o Git e as Dependências
Vamos instalar o `git`, que permitirá que baixemos o código-fonte, e o `build-essential`, que compila o código:
```
$ sudo apt-get install git build-essential -y
```
Depois, vamos instalar as dependências restantes:
```
$ sudo apt-get install libtool autotools-dev automake pkg-config bsdmainutils python3 libssl-dev libevent-dev libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libminiupnpc-dev libzmq3-dev libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler ccache -y
```
### Etapa 3: Baixando o Código-Fonte
Assim que as dependências forem instaladas, baixamos o repositório (repo) que contém o código-fonte do Bitcoin no github:
```
$ git clone https://github.com/bitcoin/bitcoin.git
```
Vamos verificar o conteúdo do repo:
```
$ ls bitcoin
```
Devemos corresponder aproximadamente ao seguinte conteúdo:
![clonando o repo](./public/LBftCLI-compiling_bitcoin-git.png)
### Etapa 4: Instalando o Berkley DB v4.8
1. Vamos entrar no diretório `contrib`:`$ cd bitcoin/contrib/`;
2. Vamos executar o seguinte comando: ```$ ./install_db4.sh `pwd` ```.
Depois de fazer o download, veremos o seguinte retorno. Devemos observar bem este retorno, porque o usaremos para configurar o bitcoin durante o build:
![db4](./public/LBftCLI-compiling_bitcoin-db4.png)
### Etapa 5: Compilando o Bitcoin Core
É recomendado que compilemos a partir de um branch com tag, que é mais estável, a menos que queiramos experimentar as últimas novidades do desenvolvimento do bitcoin. Vamos executar o seguinte comando para obter a lista de tags, ordenada a partir das mais recentes:
```
$ git tag -n | sort -V
```
Em seguida, vamos escolha uma tag, por exemplo a `v0.20.0`:
```
$ git checkout <TAG>
```
Depois de selecionar um ramo da tag, vamos executar o seguinte, dentro do diretório `bitcoin`. O `<PATH-TO>` deve ser o retorno do script `install_db4.sh`.
```
$ ./autogen.sh
$ export BDB_PREFIX='<PATH-TO>/db4'
$ ./configure BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" BDB_CFLAGS="-I${BDB_PREFIX}/include"
$ make # build bitcoin core
```
### Etapa 6: Testando o Build
Se quisermos verificar nossa compilação (o que é uma boa ideia), podemos executar os seguintes testes:
1. `$ make check` irá executar os Testes de Unidade (unit tests), que devem retornar `PASS`;
2. `$ test/functional/test_runner.py --extended` executará os testes funcionais estendidos. Podemos retirar a sinalização `--extended` se quisermos pular alguns testes. Isso vai demorar um pouco.
### Etapa 7: Executando ou Instalando o Bitcoin Core
Agora que compilamos o Bitcoin Core a partir da fonte, podemos começar a usá-lo ou instalá-lo.
#### Executando o Bitcoin Core sem Instalar
Para executar o Bitcoin Core:
`$ src/qt/bitcoin-qt` para iniciar a GUI;
`$ src/bitcoind` para executar bitcoin na linha de comando.
### Instalando o Bitcoin Core
Para instalar:
`$ sudo make install` irá instalar o Bitcoin Core globalmente. Uma vez instalado, podemos executar o bitcoin de qualquer lugar usando a linha de comando, assim como qualquer outro software, como: `$ bitcoin-qt` para a GUI ou `bitcoind` e então `bitcoin-cli` para a linha de comando.
## Finalizando Nosso Sistema
Ao compilar Bitcoin a partir da fonte, aumentamos a confiança que temos em nossa configuração. No entanto, estamos muito aquém de toda a segurança adicional fornecida por uma configuração Bitcoin Standup. Para resolver isso, podemos percorrer todo o [Linode Stackscript](https://github.com/BlockchainCommons/Bitcoin-Standup-Scripts/blob/master/Scripts/LinodeStandUp.sh) e executar passo a passo todos os comandos. O único lugar que precisamos ter cuidado é na Etapa 6, que instala o Bitcoin, pulando o ponto onde já verificamos os binários e continando a partir daí.
## Resumo: Compilando Bitcoin da Fonte
Se quisermos aumentar a segurança da instalação do Bitcoin a partir da fonte, agora sabemos fazê-lo. Felizmente, também passamos pelo Linode Stackscript para configurar um servidor mais seguro.
## O Que Vem Depois?
Se estávamos no processo de criação de um node Bitcoin para usar neste curso, devemos continuar com o [Capítulo 3: Compreendendo Nossa Configuração do Bitcoin](03_0_Understanding_Your_Bitcoin_Setup.md).
Se estivermos lendo os apêndices, vamos continuar com o [Apêndice 3: Usando o Bitcoin Regtest](A3_0_Using_Bitcoin_Regtest.md).

View File

@ -0,0 +1,206 @@
# Apêndice 3: Usando o Bitcoin Regtest
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.
A maior parte deste curso presume que usaremos a Mainnet ou a Testnet. No entanto, essas não são as únicas opções. Ao desenvolver aplicações no Bitcoin, podemos querer manter nossos aplicativos isolados das blockchains públicas. Para fazer isso, podemos criar uma blockchain do zero usando a Regtest, que tem uma outra grande vantagem sobre a Testnet. Escolhemos quando criar novos blocos, para ter controle total sobre o ambiente.
## Iniciando o Bitcoind na Regtest
Depois de [configurar nosso Bitcoin-Core em um VPS](02_0_Setting_Up_a_Bitcoin-Core_VPS.md) ou depois de [compilarmos da fonte](A2_0_Compiling_Bitcoin_from_Source.md), podemos usar a regtest. Para iniciar o `bitcoind` na regtest e criar uma blockchain privada, iremos usar o seguinte comando:
```
$ bitcoind -regtest -daemon -fallbackfee=1.0 -maxtxfee=1.1
```
Os argumentos `-fallbackfee=1.0 -maxtxfee=1.1` irão prevenir o erro `Fee estimation failed. Fallbackfee is disabled`.
No teste, geralmente não há transações suficientes, então o bitcoind não pode dar uma estimativa confiável e, sem ela, a carteira não criará transações a menos que seja explicitamente definida a taxa.
### Redefinindo a Blockchain Regtest
Se desejarmos, podemos reiniciar nossa Regtest posteriormente com uma nova blockchain.
As carteiras da Regtest e o estado da blockchain (chainstate) são salvos no subdiretória regtest do diretório de configuração do Bitcoin:
```
user@mybtc:~/.bitcoin# ls
bitcoin.conf regtest testnet3
```
Para iniciar uma nova blockchain usando a regtest, tudo que precisamos fazer é excluir a pasta `regtest` e reiniciar o Bitcoind:
```
$ rm -rf regtest
```
## Gerando uma Carteira da Regtest
Antes de gerar os blocos, é necessário carregar uma carteira usando `loadwallet` ou criar uma nova com `createwallet`. Desde a versão 0.21, o Bitcoin Core não cria automaticamente novas carteiras na inicialização.
O argumento `descriptors=true` cria uma carteira de descritores nativos, que armazena informações no scriptPubKey usando descritores de saída. Se for `false`, ele criará uma carteira legada, onde as chaves são usadas para gerar scriptPubKeys e endereços implicitamente.
```
$ bitcoin-cli -regtest -named createwallet wallet_name="regtest_desc_wallet" descriptors=true
```
## Gerando Blocos
Podemos gerar (minerar) novos blocos em uma blockchain de regtest usando o método RPC `generate` com um argumento para quantos blocos queremos gerar. Só faz sentido usar esse método na regtest; devido à grande dificuldade, é muito improvável que ele produza novos blocos na rede principal ou na rede de teste:
```
$ bitcoin-cli -regtest -generate 101
[
"57f17afccf28b9296048b6370312678b6d8e48dc3a7b4ef7681d18ed3d91c122",
"631ff7b8135ce633c774828be3b8505726459eb65c339aab981b10363befe5a7",
...
"1162dbfe025c7da94ee1128dc26d518a94508f532c19edc0de6bc673a909d02c",
"20cb2e815c3d42d6a117a204a0b5e726ab641c826e441b5b3417aca33f2aba48"
]
```
> :warning: **AVISO**. Note que devemos adicionar o argumento `-regtest` após cada comando `bitcoin-cli` para acessar corretamente nosso ambiente Regtest. Ou, se preferirmos, podemos incluir um comando `regtest=1` em nosso arquivo de configuração em `~/.bitcoin/bitcoin.conf`.
Como um bloco deve ter 100 confirmações antes que a recompensa possa ser gasta, iremos gerar 101 blocos, fornecendo acesso à transação da coinbase do bloco #1. Como esta é uma nova blockchain usando as regras padrão do Bitcoin, os primeiros blocos pagam uma recompensa de bloco de 50 bitcoins. Ao contrário do mainnet, no moda regtest apenas os primeiros 150 blocos pagam uma recompensa de 50 bitcoins. A recompensa diminui pela metade após 150 blocos, então paga 25, 12,5 e assim por diante...
A saída é o hash de cada bloco gerado.
> :book: ***O que é uma transação do tipo coinbase?*** Uma coinbase é a transação sem entrada criada quando um novo bloco é extraído e entregue ao minerador. É assim que novos bitcoins entram no ecossistema. O valor das transações coinbase decai com o tempo. Na rede principal, ele cai pela metade a cada 210.000 blocos e termina inteiramente com o bloco 6.929.999, que está previsto atualmente para o século 22. Em maio de 2020, a recompensa pela coinbase é 6,25 BTC.
### Verificando Nosso Saldo
Depois de minerar os blocos e receber as recompensas, podemos verificar o saldo em nossa carteira:
```
$ bitcoin-cli -regtest getbalance
50.00000000
```
## Usando a Regtest
Agora devemos ser capazes de usar este saldo para qualquer tipo de interação em nossa blockchain privada, como o envio de transações Bitcoin de acordo com o [Capítulo 4](04_0_Sending_Bitcoin_Transactions.md).
É importante notar que para que qualquer transação seja concluída, teremos que gerar (minerar) novos blocos, para que as transações possam ser incluídas.
Por exemplo, para criar uma transação e incluí-la em um bloco, devemos primeiro usar o comando `sendtoaddress`:
```
$ bitcoin-cli -regtest sendtoaddress [address] 15.1
e834a4ac6ef754164c8e3f0be4f34531b74b768199ffb244ab9f6cb1bbc7465a
```
A saída é o hash da transação incluída na blockchain. Podemos verificar os detalhes usando `gettransaction`:
```
$ bitcoin-cli -regtest gettransaction e834a4ac6ef754164c8e3f0be4f34531b74b768199ffb244ab9f6cb1bbc7465a
{
"amount": 0.00000000,
"fee": -0.00178800,
"confirmations": 0,
"trusted": false,
"txid": "e834a4ac6ef754164c8e3f0be4f34531b74b768199ffb244ab9f6cb1bbc7465a",
"walletconflicts": [
],
"time": 1513204730,
"timereceived": 1513204730,
"bip125-replaceable": "unknown",
"details": [
{
"account": "",
"address": "mjtN3C97kuWMgeBbxdB7hG1bjz24Grx2vA",
"category": "send",
"amount": -15.10000000,
"label": "",
"vout": 1,
"fee": -0.00178800,
"abandoned": false
},
{
"account": "",
"address": "mjtN3C97kuWMgeBbxdB7hG1bjz24Grx2vA",
"category": "receive",
"amount": 15.10000000,
"label": "",
"vout": 1
}
],
"hex": "020000000f00fe2c7b70b925d0d40011ce96f8991fee5aba9537bd1b6913b37c37b041a57c00000000494830450221009ad02bfeee2a49196a99811ace20e2e7fefd16d33d525884edbc64bf6e2b1db502200b94f4000556391b0998932edde3033ba2517733c7ddffb87d91f6b756629fe201feffffff06a9301a2b39875b68f8058b8e2ad0b658f505e44a67e1e1d039140ae186ed1f0000000049483045022100c65cd13a85af6fcfba74d2852276a37076c89a7642429aa111b7986eea7fd6c7022012bbcb633d392ed469d5befda8df0a6b96e1acfa342f559877edebc2af7cb93401feffffff434b6f67e5e068401553e89f739a3edc667504597f29feb8edafc2b081cc32d90000000049483045022100b86ecc43e602180c787c36465da7fc8d1e8bfba23d6f49c37190c20889f2dfa0022032c3aec3ceefbb7a33c040ef19090cacbfd6bc9c5cd8e94252eb864891c6f34501feffffff4c65b43f8568ce58fc4c55d24ba0742e9878a031fdfae0fadac7247f42cc1f8e0000000049483045022100d055acfce852259dde051dc61792f94277d094c5da96752f925582b8e739868f02205e69add76e6b001073ad6b7df5f32a681fc8513ee0f6e126ee1c2d45149bd91d01feffffff5a72d60b58300974c5d4731e29b437ea61b87b6733bb3ca6ce5548ef8887d05b0000000049483045022100a7f5b2ee656a5a904fb27f982210de6858dfb165777ec969a77ea1c2c82975a4022001a1a563dbc3714047ec855f7aee901e756b851e255f35435e85c2ba7b0abd8401feffffff60d68e9d5650d55bc9e0b2a65ed27a3b9bceac4955760aa1560408854c3b148d000000004948304502210081a6f0c8232c52f3eaca825965077e88b816e503834989be4afb3f44f87eb98202207ae8becb99efe379fb269f477e7bb70d117dcb83e106c53b7addaa9715029da101feffffff63e2239425aad544f6e1157d5ee245d2500d4e9e9daf8049e0a38add6246da890000000049483045022100e0ab1752e8fbb244b63f7dd5649f2222e0dc42fae293b758e0c28082f77560b60220013f72fbe50acf4af197890b4d18fa89094055ed66f9226a6b461cc4ff560f8e01feffffff6aad4151087f4209ace714193dd64f770305dfb89470b79cca538b88253fbbef0000000049483045022100fee4a5f7ec6e8b55bd6aa0e93b5399af724039171d998b926e8095b70953d5f202203db0d4ef9d1bd57aeff0fe3d47d4358ec0559135dac8107507741eef0638279201feffffff7ddbca5854e25e6a2dfeacfe5828267cd1ef5d86e1da573fe2c2b21b45ecd6ce0000000049483045022100bf45241525592df4625642972dbc940ef74771139dd844bc6a9517197d01488c02203c99ca98892cc2693e8fbb9a600962eec84494fb8596acf0d670822624e497c901feffffff8672949de559e76601684c4ac3731599fd965d0c412e7df9f8ec16038d4420a60000000049483045022100b5a9bd3c6718c6bd2a8300bbd1d9de0ff1c5d02aeb6a659c52bb88958e7e3b0302207f710db1ef975c22edf54e063169aae31bbe470166cc0e5c34fd27b730b8e7d001feffffff8e006b0bb8cef2c5c2a11c8c2aa7d3ba01cb4386c7f780c45bc1014142b425f00000000048473044022046dc9db8daeb09b7c0b9f48013c8af2d0a71f688adaa8d91b40891768c852d4a02204fa15da6d58851191344a56c63bf51a540ec03f73117a3446230bb58a8a4bcce01feffffffbad05b8f86182b9b7c9c5aaa9ce3dc8d08a76848e49a2d9b8dcfb0f764bb26ca000000004847304402200682379dc36cb486309eac4913f41ac19638525677edad45ca8d9a2b0728b12f02203fb44f8a46cbc4c02f5699d7d4d9cd810bdf7e7c981b421218ccbcb7b73845f501feffffffd35228fe9ef0a742eacffc4a13f15ed7ba23854e6cb49d5010810ac11b5bdf690000000048473044022030045b882500808bd707f4654becc63de070818c82716310d39576decdd724e3022034d3b41cb5e939f0011bb5251be7941b6077fde5f4eff59afd8e49a2844288f701fefffffff5ae4cbd4ae8d68b5a34be3231cdc88b660447175f39cf7a86397f37641d4aa70000000049483045022100afe16f0de96a8629d6148f93520d690f30126c37e7f7f05300745a1273d7eb7202200933f6b371c4ea522570f3ec2aee9be2b59730b634e828f543bcdb019cf4749901fefffffff633f61ac61683221cc3d2665cf4bcf193af1c8ffe9d3d756ba83cc5eb7643250000000049483045022100ef0b8853c94d60634eff2fc1d4d75872aacb0a2d3242308b7ee256b24739c614022069fe9be8288bdd635871c263c46be710c001729d43f6fbc1350ed1a693c4646301feffffff0250780000000000001976a91464ed7fb2fe0b06f4cad0d731b122222e3e91088a88ac80c5005a000000001976a9142fed0f02d008f89f6a874168e506e2d4f9bcbfb888acd32b0000"
}
```
No entanto, agora devemos finalizá-la criando blocos na blockchain.
A maioria das aplicações requer seis confirmações de bloco para considerar a transação como irreversível. Se este for o nosso caso, podemos minerar seis blocos adicionais em nossa blockchain de teste:
```
$ bitcoin-cli -regtest -generate 6
[
"33549b2aa249f0a814db4a2ba102194881c14a2ac041c23dcc463b9e4e128e9f",
"2cc5c2012e2cacf118f9db4cdd79582735257f0ec564418867d6821edb55715e",
"128aaa99e7149a520080d90fa989c62caeda11b7d06ed1965e3fa7c76fa1d407",
"6037cc562d97eb3984cca50d8c37c7c19bae8d79b8232b92bec6dcc9708104d3",
"2cb276f5ed251bf629dd52fd108163703473f57c24eac94e169514ce04899581",
"57193ba8fd2761abf4a5ebcb4ed1a9ec2e873d67485a7cb41e75e13c65928bf3"
]
```
## Testando com NodeJS
Quando estamos fazendo testes, somos capazes de simular casos extremos e ataques que podem acontecer no mundo real, como o problema de gasto duplo.
Conforme discutido em outro lugar neste curso, o uso de bibliotecas de software pode fornecer acesso mais sofisticado a alguns comandos RPC. Nesse caso, o [bitcointest criado por dgarage](https://github.com/dgarage/bitcointest) para o NodeJS pode ser usado para simular uma transação de uma carteira para outra; podemos verificar [a documentação](https://www.npmjs.com/package/bitcointest) para simularmos ataque mais específicos, como o de gasto duplo.
Vejamos a seção [§18.3](18_3_Accessing_Bitcoind_with_NodeJS.md) para as informações mais atualizadas sobre a instalação do NodeJS, em seguida, podemos adicionar ao `bitcointest`:
```
$ npm install -g bitcointest
```
Depois de instalar o `bitcointest`, podemos criar um arquivo `test.js` com o seguinte conteúdo:
```javascript
file: test.js
const { BitcoinNet, BitcoinGraph } = require('bitcointest');
const net = new BitcoinNet('/usr/local/bin', '/tmp/bitcointest/', 22001, 22002);
const graph = new BitcoinGraph(net);
try {
console.log('Launching nodes...');
const nodes = net.launchBatchS(4);
const [ n1, n2 ] = nodes;
net.waitForNodesS(nodes, 20000);
console.log('Connected!');
const blocks = n1.generateBlocksS(110);
console.info('Generated 110 blocks');
console.log(`n2.balance (before) = ${n2.getBalanceS()}`);
const sometxid = n1.sendToNodeS(n2, 100);
console.log(`Generated transaction = ${sometxid}`);
n1.generateBlocksS(110);
n2.waitForBalanceChangeS(0);
const sometx = n2.getTransactionS(sometxid);
console.log(`n2.balance (after) = ${n2.getBalanceS()}`);
} catch (e) {
console.error(e);
net.shutdownS();
throw e;
}
```
Conforme mostrado, isso irá gerar blocos e uma transação:
```
$ node test.js
Launching nodes...
Connected!
Generated 110 blocks
n2.balance (before) = 0
Generated transaction = 91e0040c26fc18312efb80bad6ec3b00202a83465872ecf495c392a0b6afce35
n2.after (before) = 100
```
## Resumo: Usando o Bitcoin Regtest
Um ambiente regtest para o Bitcoin funciona como qualquer ambiente testnet, exceto que teremos a capacidade de gerar blocos de maneira rápida e fácil.
> :fire: ***Qual é o poder da regtest?*** O maior poder da regtest é que podemos minerar blocos rapidamente, permitindo que nos apressemos na blockchain para testar transações, timelocks e outros recursos que podemos querer, caso contrário, teríamos de sentar e esperar. No entanto, o outro poder é que podemos executar de forma privada, sem nos conectarmos a uma blockchain pública, nos permitindo testar nossas ideias antes de liberá-las para o mundo.
## O Que Vem Depois?
Se estamos visitando o Apêndice enquanto trabalhamos em alguma outra parte do curso, devemos voltar para lá.
Mas, caso contrário, chegamos ao fim! Outras pessoas que trabalharam neste curso tornaram-se desenvolvedores e engenheiros profissionais no mundo do Bitcoin, incluindo alguns dos quais contribuíram para a [Blockchain Commons](https://www.blockchaincommons.com/). Nós o encorajamos a fazer o mesmo! Basta sair e começar a trabalhar em alguns dos códigos do Bitcoin usando o que aprendemos.

64
pt/CONTRIBUTING.md Normal file
View File

@ -0,0 +1,64 @@
# Contribuindo
Nós adoramos a sua contribuição! Queremos deixar o processo de contribuir para este repositório o mais fácil e transparente possível, independente se é para:
- Reportar um bug
- Discutir o estado atual do código
- Enviar uma correção
- Propor novas funcionalidades
- Se tornar um mantenedor
## Nós Desenvolvemos com o Github
Usamos o GitHub para hospedar o código, rastrear issues e solicitações de recursos e aceitar Pull Requests.
## Reporte Bugs usando os [issues](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/issues) do GitHub
Se você encontrar bugs, erros ou inconsistências no código ou nos documentos deste projeto, informe-nos [abrindo um novo issue](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/issues/new), mas considere pesquisar os problemas existentes primeiro para verificar se o problema já foi relatado. Se tiver, nunca é demais adicionar um rápido "+1" ou "Eu também tenho esse problema". Isso ajuda a priorizar os problemas e solicitações mais comuns.
### Escreva Relatórios de Bug com Detalhes, Contexto e Código de Amostra
[Este é um exemplo](http://stackoverflow.com/q/12488905/180626) de um bom relatório de bug por @briandk. Aqui está [outro exemplo de craig.hockenberry](http://www.openradar.me/11905408).
**Ótimos relatórios de bug** tendem a ter:
- Um resumo e/ou contexto rápido
- Passos para reproduzir
- Seja específico!
- Forneça um código de amostra, se puder. [O relatório de bug do StackOverflow](http://stackoverflow.com/q/12488905/180626) inclui código de amostra que *qualquer pessoa* com uma configuração básica de R pode executar para reproduzir o que eu estava vendo
- O que você esperava que acontecesse
- O que realmente acontece
- Observações (possivelmente incluindo por que você acha que isso pode estar acontecendo ou coisas que você tentou que não funcionaram)
As pessoas *adoram* relatórios de bug completos. Sem brincadeira.
## Envie Alterações de Código por meio de Pull Requests
Pull Requests simples para corrigir erros de digitação, documentar ou corrigir pequenos bugs são sempre bem-vindas.
Pedimos que melhorias mais significativas para o projeto sejam propostas, antes que alguém comece a programar, como um [issue](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/issues) ou como uma [Pull Request de rascunho](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/pulls), que é um [novo recurso interessante](https://github.blog/2019-02-14-introducing-draft-pull-requests/) que dá a outros contribuidores a chance de apontar a direção certa, dar feedback sobre o design e talvez discutir se o trabalho relacionado já está em andamento.
### Use um Estilo de Programação Consistente
* Recuamos usando dois espaços (soft tabs)
* SEMPRE colocamos espaços após os itens da lista e parâmetros do método ([1, 2, 3], não [1,2,3]), ao redor dos operadores (x + = 1, não x + = 1) e ao redor de setas hash.
* Este é um software de código aberto. Considere as pessoas que lerão seu código e faça com que ele tenha uma boa aparência para elas. É como dirigir um carro: talvez você adore fazer zerinhos quando está sozinho, mas com os passageiros o objetivo é tornar a viagem o mais suave possível.
### Use [Github Flow](https://guides.github.com/introduction/flow/index.html) para Pull Requests
Usamos [Github Flow](https://guides.github.com/introduction/flow/index.html). Ao enviar Pull Requests, por favor:
1. Faça um fork do repo e crie seu branch a partir do `master`.
2. Se você adicionou um código que deve ser testado, adicione testes.
3. Se você alterou APIs, atualize a documentação.
4. Certifique-se de que o conjunto de testes seja aprovado.
5. Certifique-se de que seu código passe por um lint.
6. Emita essa Pull Request!
### Envie Sob a Licença de Patente BSD-2-Clause Plus
Resumindo, quando você envia alterações de código, seus envios são considerados disponíveis sob a mesma licença [CC-BY](../LICENSE-CC-BY-4.0.md) que cobre o projeto. Também pedimos que todos os contribuidores de código do GPG assinem o [Contrato de Licença de Contribuidor (CLA.md)](../CLA.md) para proteger futuros usuários deste projeto. Sinta-se à vontade para entrar em contato com os mantenedores se isso for um problema.
## Referências
Partes deste documento CONTRIBUTING.md foram adotadas a partir das melhores práticas de uma série de projetos de código aberto, incluindo:
* [Rascunho do Facebook](https://github.com/facebook/draft-js/blob/a9316a723f9e918afde44dea68b5f9f39b7d9b00/CONTRIBUTING.md)
* [Contribuição de IPFS](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)

Some files were not shown because too many files have changed in this diff Show More